diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..5d47c21c --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +# EditorConfig is awesome: https://EditorConfig.org + +# top-most EditorConfig file +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true diff --git a/.envrc b/.envrc new file mode 100644 index 00000000..3550a30f --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake diff --git a/.forgejo/workflows/lint.yml b/.forgejo/workflows/lint.yml new file mode 100644 index 00000000..85b68639 --- /dev/null +++ b/.forgejo/workflows/lint.yml @@ -0,0 +1,22 @@ +name: Lint + +on: [push] + +jobs: + lint: + runs-on: docker + env: + container: + image: ghcr.io/catthehacker/ubuntu:js-20.04 + steps: + - uses: actions/checkout@v3 + - uses: https://github.com/cachix/install-nix-action@v22 + env: + with: + nix_path: nixpkgs=channel:nixos-unstable + - run: | + sed -i '/^access-tokens/ d' /etc/nix/nix.conf + nix profile install 'nixpkgs#deadnix' 'nixpkgs#statix' 'nixpkgs#yamllint' + statix check . + deadnix -f + yamllint . diff --git a/.forgejo/workflows/nix.yml b/.forgejo/workflows/nix.yml new file mode 100644 index 00000000..a67c4890 --- /dev/null +++ b/.forgejo/workflows/nix.yml @@ -0,0 +1,22 @@ +name: Nix + +# on: [push] + +jobs: + lint: + runs-on: docker + env: + container: + image: ghcr.io/catthehacker/ubuntu:js-20.04 + steps: + - uses: actions/checkout@v3 + - name: Check Nix flake inputs + uses: https://github.com/DeterminateSystems/flake-checker-action@v5 + - uses: https://github.com/cachix/install-nix-action@v22 + env: + with: + nix_path: nixpkgs=channel:nixos-unstable + - name: Run `nix flake check` + run: | + sed -i '/^access-tokens/ d' /etc/nix/nix.conf + nix run '.#' -- -V diff --git a/.forgejo/workflows/plex_update.yml b/.forgejo/workflows/plex_update.yml new file mode 100644 index 00000000..2d5a2393 --- /dev/null +++ b/.forgejo/workflows/plex_update.yml @@ -0,0 +1,37 @@ +name: Plex Update + +on: + push: + branches: + - main + - ci + schedule: + - cron: '0 0 * * *' + +jobs: + update: + runs-on: docker + container: + image: ghcr.io/catthehacker/ubuntu:js-20.04 + steps: + - uses: actions/checkout@v3 + - uses: https://github.com/cachix/install-nix-action@v22 + with: + nix_path: nixpkgs=channel:nixos-unstable + - env: + VAULT_ADDR: ${{ secrets.VAULT_ADDR }} + VAULT_TOKEN: ${{ secrets.VAULT_TOKEN }} + run: | + git config user.name "Forgejo Actions Bot" + git config user.email "<>" + + # Run Update script + ./nixos/pkgs/plex-pass/update.sh + + git add ./nixos/pkgs/plex-pass/ + + # Push if changed + if git status ./nixos/pkgs/plex-pass/ | grep -q "to be committed"; then + git commit -m "Update Plex" + git push origin main + fi diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..263c0ce2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +result +.direnv +.gcroots \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..50f57ec0 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "Lua.diagnostics.globals": [ + "vim" + ] +} \ No newline at end of file diff --git a/.vscode/snippets.code-snippets b/.vscode/snippets.code-snippets new file mode 100644 index 00000000..cc364cc7 --- /dev/null +++ b/.vscode/snippets.code-snippets @@ -0,0 +1,31 @@ +{ + // Place your infrastructure workspace snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and + // description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope + // is left empty or omitted, the snippet gets applied to all languages. The prefix is what is + // used to trigger the snippet and the body will be expanded and inserted. Possible variables are: + // $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders. + // Placeholders with the same ids are connected. + // Example: + // "Print to console": { + // "scope": "javascript,typescript", + // "prefix": "log", + // "body": [ + // "console.log('$1');", + // "$2" + // ], + // "description": "Log output to console" + // } + "Create Host": { + "scope": "nix", + "prefix": "new_host", + "body": [ + "{", + " hostname = \"$1\";", + " ip = \"$2\";", + " mac = \"$3\";", + " nix = ${4|false,true|};", + "}", + "$0" + ] + } +} diff --git a/.yamllint.yaml b/.yamllint.yaml new file mode 100644 index 00000000..95191b4a --- /dev/null +++ b/.yamllint.yaml @@ -0,0 +1,27 @@ +ignore: | + charts/ + docs/ + .private/ + .terraform/ + .vscode/ + gotk-components.yaml + gotk-sync.yaml +extends: default +rules: + document-start: + level: warning + present: false + empty-lines: + max-end: 1 + truthy: + allowed-values: ["true", "false", "on"] + comments: + min-spaces-from-content: 1 + line-length: disable + braces: + min-spaces-inside: 0 + max-spaces-inside: 1 + brackets: + min-spaces-inside: 0 + max-spaces-inside: 0 + indentation: enable diff --git a/README.md b/README.md new file mode 100644 index 00000000..373e02b7 --- /dev/null +++ b/README.md @@ -0,0 +1,18 @@ +# 0x76's Infrastructure +This repository contains my fleet of VMs, Containers and Bare Metal machines. + +## Directory Structure +`flake.nix` is a NixOS flake which is the entrypoint for my NixOS config, it also contains a 'DevShell' containing all the tools needed +to deploy the infrastructure, this can be accessed running `nix develop`. +* **flux**: Kubernetes manifests as managed by [Flux] +* **nixos**: Nix configurations for my NixOS LXCs and VMs, deployed using [colmena]. + + +[Flux]: https://github.com/fluxcd/flux2 +[colmena]: https://colmena.cli.rs/unstable/ + +## Inspired by the following repos +* +* +* +* diff --git a/cluster/flux-system/gotk-components.yaml b/cluster/flux-system/gotk-components.yaml deleted file mode 100644 index 16f44d3e..00000000 --- a/cluster/flux-system/gotk-components.yaml +++ /dev/null @@ -1,4110 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - labels: - app.kubernetes.io/instance: flux-system - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v0.19.1 - name: flux-system ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.5.0 - creationTimestamp: null - labels: - app.kubernetes.io/instance: flux-system - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v0.19.1 - name: alerts.notification.toolkit.fluxcd.io -spec: - group: notification.toolkit.fluxcd.io - names: - kind: Alert - listKind: AlertList - plural: alerts - singular: alert - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Status - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1beta1 - schema: - openAPIV3Schema: - description: Alert is the Schema for the alerts API - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: AlertSpec defines an alerting rule for events involving a - list of objects - properties: - eventSeverity: - default: info - description: Filter events based on severity, defaults to ('info'). - If set to 'info' no events will be filtered. - enum: - - info - - error - type: string - eventSources: - description: Filter events based on the involved objects. - items: - description: CrossNamespaceObjectReference contains enough information - to let you locate the typed referenced object at cluster level - properties: - apiVersion: - description: API version of the referent - type: string - kind: - description: Kind of the referent - enum: - - Bucket - - GitRepository - - Kustomization - - HelmRelease - - HelmChart - - HelmRepository - - ImageRepository - - ImagePolicy - - ImageUpdateAutomation - type: string - name: - description: Name of the referent - maxLength: 53 - minLength: 1 - type: string - namespace: - description: Namespace of the referent - maxLength: 53 - minLength: 1 - type: string - required: - - name - type: object - type: array - exclusionList: - description: A list of Golang regular expressions to be used for excluding - messages. - items: - type: string - type: array - providerRef: - description: Send events using this provider. - properties: - name: - description: Name of the referent - type: string - required: - - name - type: object - summary: - description: Short description of the impact and affected cluster. - type: string - suspend: - description: This flag tells the controller to suspend subsequent - events dispatching. Defaults to false. - type: boolean - required: - - eventSources - - providerRef - type: object - status: - default: - observedGeneration: -1 - description: AlertStatus defines the observed state of Alert - properties: - conditions: - items: - description: "Condition contains details for one aspect of the current - state of this API Resource. --- This struct is intended for direct - use as an array at the field path .status.conditions. For example, - type FooStatus struct{ // Represents the observations of a - foo's current state. // Known .status.conditions.type are: - \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type - \ // +patchStrategy=merge // +listType=map // +listMapKey=type - \ Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` - \n // other fields }" - properties: - lastTransitionTime: - description: lastTransitionTime is the last time the condition - transitioned from one status to another. This should be when - the underlying condition changed. If that is not known, then - using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: message is a human readable message indicating - details about the transition. This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: observedGeneration represents the .metadata.generation - that the condition was set based upon. For instance, if .metadata.generation - is currently 12, but the .status.conditions[x].observedGeneration - is 9, the condition is out of date with respect to the current - state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: reason contains a programmatic identifier indicating - the reason for the condition's last transition. Producers - of specific condition types may define expected values and - meanings for this field, and whether the values are considered - a guaranteed API. The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - --- Many .condition.type values are consistent across resources - like Available, but because arbitrary conditions can be useful - (see .node.status.conditions), the ability to deconflict is - important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - observedGeneration: - description: ObservedGeneration is the last observed generation. - format: int64 - type: integer - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.5.0 - creationTimestamp: null - labels: - app.kubernetes.io/instance: flux-system - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v0.19.1 - name: buckets.source.toolkit.fluxcd.io -spec: - group: source.toolkit.fluxcd.io - names: - kind: Bucket - listKind: BucketList - plural: buckets - singular: bucket - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .spec.url - name: URL - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Status - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1beta1 - schema: - openAPIV3Schema: - description: Bucket is the Schema for the buckets API - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: BucketSpec defines the desired state of an S3 compatible - bucket - properties: - bucketName: - description: The bucket name. - type: string - endpoint: - description: The bucket endpoint address. - type: string - ignore: - description: Ignore overrides the set of excluded patterns in the - .sourceignore format (which is the same as .gitignore). If not provided, - a default will be used, consult the documentation for your version - to find out what those are. - type: string - insecure: - description: Insecure allows connecting to a non-TLS S3 HTTP endpoint. - type: boolean - interval: - description: The interval at which to check for bucket updates. - type: string - provider: - default: generic - description: The S3 compatible storage provider name, default ('generic'). - enum: - - generic - - aws - - gcp - type: string - region: - description: The bucket region. - type: string - secretRef: - description: The name of the secret containing authentication credentials - for the Bucket. - properties: - name: - description: Name of the referent - type: string - required: - - name - type: object - suspend: - description: This flag tells the controller to suspend the reconciliation - of this source. - type: boolean - timeout: - default: 20s - description: The timeout for download operations, defaults to 20s. - type: string - required: - - bucketName - - endpoint - - interval - type: object - status: - description: BucketStatus defines the observed state of a bucket - properties: - artifact: - description: Artifact represents the output of the last successful - Bucket sync. - properties: - checksum: - description: Checksum is the SHA1 checksum of the artifact. - type: string - lastUpdateTime: - description: LastUpdateTime is the timestamp corresponding to - the last update of this artifact. - format: date-time - type: string - path: - description: Path is the relative file path of this artifact. - type: string - revision: - description: Revision is a human readable identifier traceable - in the origin source system. It can be a Git commit SHA, Git - tag, a Helm index timestamp, a Helm chart version, etc. - type: string - url: - description: URL is the HTTP address of this artifact. - type: string - required: - - path - - url - type: object - conditions: - description: Conditions holds the conditions for the Bucket. - items: - description: "Condition contains details for one aspect of the current - state of this API Resource. --- This struct is intended for direct - use as an array at the field path .status.conditions. For example, - type FooStatus struct{ // Represents the observations of a - foo's current state. // Known .status.conditions.type are: - \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type - \ // +patchStrategy=merge // +listType=map // +listMapKey=type - \ Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` - \n // other fields }" - properties: - lastTransitionTime: - description: lastTransitionTime is the last time the condition - transitioned from one status to another. This should be when - the underlying condition changed. If that is not known, then - using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: message is a human readable message indicating - details about the transition. This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: observedGeneration represents the .metadata.generation - that the condition was set based upon. For instance, if .metadata.generation - is currently 12, but the .status.conditions[x].observedGeneration - is 9, the condition is out of date with respect to the current - state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: reason contains a programmatic identifier indicating - the reason for the condition's last transition. Producers - of specific condition types may define expected values and - meanings for this field, and whether the values are considered - a guaranteed API. The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - --- Many .condition.type values are consistent across resources - like Available, but because arbitrary conditions can be useful - (see .node.status.conditions), the ability to deconflict is - important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - lastHandledReconcileAt: - description: LastHandledReconcileAt holds the value of the most recent - reconcile request value, so a change can be detected. - type: string - observedGeneration: - description: ObservedGeneration is the last observed generation. - format: int64 - type: integer - url: - description: URL is the download link for the artifact output of the - last Bucket sync. - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.5.0 - creationTimestamp: null - labels: - app.kubernetes.io/instance: flux-system - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v0.19.1 - name: gitrepositories.source.toolkit.fluxcd.io -spec: - group: source.toolkit.fluxcd.io - names: - kind: GitRepository - listKind: GitRepositoryList - plural: gitrepositories - shortNames: - - gitrepo - singular: gitrepository - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .spec.url - name: URL - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Status - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1beta1 - schema: - openAPIV3Schema: - description: GitRepository is the Schema for the gitrepositories API - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: GitRepositorySpec defines the desired state of a Git repository. - properties: - gitImplementation: - default: go-git - description: Determines which git client library to use. Defaults - to go-git, valid values are ('go-git', 'libgit2'). - enum: - - go-git - - libgit2 - type: string - ignore: - description: Ignore overrides the set of excluded patterns in the - .sourceignore format (which is the same as .gitignore). If not provided, - a default will be used, consult the documentation for your version - to find out what those are. - type: string - include: - description: Extra git repositories to map into the repository - items: - description: GitRepositoryInclude defines a source with a from and - to path. - properties: - fromPath: - description: The path to copy contents from, defaults to the - root directory. - type: string - repository: - description: Reference to a GitRepository to include. - properties: - name: - description: Name of the referent - type: string - required: - - name - type: object - toPath: - description: The path to copy contents to, defaults to the name - of the source ref. - type: string - required: - - repository - type: object - type: array - interval: - description: The interval at which to check for repository updates. - type: string - recurseSubmodules: - description: When enabled, after the clone is created, initializes - all submodules within, using their default settings. This option - is available only when using the 'go-git' GitImplementation. - type: boolean - ref: - description: The Git reference to checkout and monitor for changes, - defaults to master branch. - properties: - branch: - default: master - description: The Git branch to checkout, defaults to master. - type: string - commit: - description: The Git commit SHA to checkout, if specified Tag - filters will be ignored. - type: string - semver: - description: The Git tag semver expression, takes precedence over - Tag. - type: string - tag: - description: The Git tag to checkout, takes precedence over Branch. - type: string - type: object - secretRef: - description: The secret name containing the Git credentials. For HTTPS - repositories the secret must contain username and password fields. - For SSH repositories the secret must contain identity, identity.pub - and known_hosts fields. - properties: - name: - description: Name of the referent - type: string - required: - - name - type: object - suspend: - description: This flag tells the controller to suspend the reconciliation - of this source. - type: boolean - timeout: - default: 20s - description: The timeout for remote Git operations like cloning, defaults - to 20s. - type: string - url: - description: The repository URL, can be a HTTP/S or SSH address. - pattern: ^(http|https|ssh):// - type: string - verify: - description: Verify OpenPGP signature for the Git commit HEAD points - to. - properties: - mode: - description: Mode describes what git object should be verified, - currently ('head'). - enum: - - head - type: string - secretRef: - description: The secret name containing the public keys of all - trusted Git authors. - properties: - name: - description: Name of the referent - type: string - required: - - name - type: object - required: - - mode - type: object - required: - - interval - - url - type: object - status: - description: GitRepositoryStatus defines the observed state of a Git repository. - properties: - artifact: - description: Artifact represents the output of the last successful - repository sync. - properties: - checksum: - description: Checksum is the SHA1 checksum of the artifact. - type: string - lastUpdateTime: - description: LastUpdateTime is the timestamp corresponding to - the last update of this artifact. - format: date-time - type: string - path: - description: Path is the relative file path of this artifact. - type: string - revision: - description: Revision is a human readable identifier traceable - in the origin source system. It can be a Git commit SHA, Git - tag, a Helm index timestamp, a Helm chart version, etc. - type: string - url: - description: URL is the HTTP address of this artifact. - type: string - required: - - path - - url - type: object - conditions: - description: Conditions holds the conditions for the GitRepository. - items: - description: "Condition contains details for one aspect of the current - state of this API Resource. --- This struct is intended for direct - use as an array at the field path .status.conditions. For example, - type FooStatus struct{ // Represents the observations of a - foo's current state. // Known .status.conditions.type are: - \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type - \ // +patchStrategy=merge // +listType=map // +listMapKey=type - \ Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` - \n // other fields }" - properties: - lastTransitionTime: - description: lastTransitionTime is the last time the condition - transitioned from one status to another. This should be when - the underlying condition changed. If that is not known, then - using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: message is a human readable message indicating - details about the transition. This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: observedGeneration represents the .metadata.generation - that the condition was set based upon. For instance, if .metadata.generation - is currently 12, but the .status.conditions[x].observedGeneration - is 9, the condition is out of date with respect to the current - state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: reason contains a programmatic identifier indicating - the reason for the condition's last transition. Producers - of specific condition types may define expected values and - meanings for this field, and whether the values are considered - a guaranteed API. The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - --- Many .condition.type values are consistent across resources - like Available, but because arbitrary conditions can be useful - (see .node.status.conditions), the ability to deconflict is - important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - includedArtifacts: - description: IncludedArtifacts represents the included artifacts from - the last successful repository sync. - items: - description: Artifact represents the output of a source synchronisation. - properties: - checksum: - description: Checksum is the SHA1 checksum of the artifact. - type: string - lastUpdateTime: - description: LastUpdateTime is the timestamp corresponding to - the last update of this artifact. - format: date-time - type: string - path: - description: Path is the relative file path of this artifact. - type: string - revision: - description: Revision is a human readable identifier traceable - in the origin source system. It can be a Git commit SHA, Git - tag, a Helm index timestamp, a Helm chart version, etc. - type: string - url: - description: URL is the HTTP address of this artifact. - type: string - required: - - path - - url - type: object - type: array - lastHandledReconcileAt: - description: LastHandledReconcileAt holds the value of the most recent - reconcile request value, so a change can be detected. - type: string - observedGeneration: - description: ObservedGeneration is the last observed generation. - format: int64 - type: integer - url: - description: URL is the download link for the artifact output of the - last repository sync. - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.5.0 - creationTimestamp: null - labels: - app.kubernetes.io/instance: flux-system - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v0.19.1 - name: helmcharts.source.toolkit.fluxcd.io -spec: - group: source.toolkit.fluxcd.io - names: - kind: HelmChart - listKind: HelmChartList - plural: helmcharts - shortNames: - - hc - singular: helmchart - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .spec.chart - name: Chart - type: string - - jsonPath: .spec.version - name: Version - type: string - - jsonPath: .spec.sourceRef.kind - name: Source Kind - type: string - - jsonPath: .spec.sourceRef.name - name: Source Name - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Status - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1beta1 - schema: - openAPIV3Schema: - description: HelmChart is the Schema for the helmcharts API - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: HelmChartSpec defines the desired state of a Helm chart. - properties: - chart: - description: The name or path the Helm chart is available at in the - SourceRef. - type: string - interval: - description: The interval at which to check the Source for updates. - type: string - reconcileStrategy: - default: ChartVersion - description: Determines what enables the creation of a new artifact. - Valid values are ('ChartVersion', 'Revision'). See the documentation - of the values for an explanation on their behavior. Defaults to - ChartVersion when omitted. - enum: - - ChartVersion - - Revision - type: string - sourceRef: - description: The reference to the Source the chart is available at. - properties: - apiVersion: - description: APIVersion of the referent. - type: string - kind: - description: Kind of the referent, valid values are ('HelmRepository', - 'GitRepository', 'Bucket'). - enum: - - HelmRepository - - GitRepository - - Bucket - type: string - name: - description: Name of the referent. - type: string - required: - - kind - - name - type: object - suspend: - description: This flag tells the controller to suspend the reconciliation - of this source. - type: boolean - valuesFile: - description: Alternative values file to use as the default chart values, - expected to be a relative path in the SourceRef. Deprecated in favor - of ValuesFiles, for backwards compatibility the file defined here - is merged before the ValuesFiles items. Ignored when omitted. - type: string - valuesFiles: - description: Alternative list of values files to use as the chart - values (values.yaml is not included by default), expected to be - a relative path in the SourceRef. Values files are merged in the - order of this list with the last file overriding the first. Ignored - when omitted. - items: - type: string - type: array - version: - default: '*' - description: The chart version semver expression, ignored for charts - from GitRepository and Bucket sources. Defaults to latest when omitted. - type: string - required: - - chart - - interval - - sourceRef - type: object - status: - description: HelmChartStatus defines the observed state of the HelmChart. - properties: - artifact: - description: Artifact represents the output of the last successful - chart sync. - properties: - checksum: - description: Checksum is the SHA1 checksum of the artifact. - type: string - lastUpdateTime: - description: LastUpdateTime is the timestamp corresponding to - the last update of this artifact. - format: date-time - type: string - path: - description: Path is the relative file path of this artifact. - type: string - revision: - description: Revision is a human readable identifier traceable - in the origin source system. It can be a Git commit SHA, Git - tag, a Helm index timestamp, a Helm chart version, etc. - type: string - url: - description: URL is the HTTP address of this artifact. - type: string - required: - - path - - url - type: object - conditions: - description: Conditions holds the conditions for the HelmChart. - items: - description: "Condition contains details for one aspect of the current - state of this API Resource. --- This struct is intended for direct - use as an array at the field path .status.conditions. For example, - type FooStatus struct{ // Represents the observations of a - foo's current state. // Known .status.conditions.type are: - \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type - \ // +patchStrategy=merge // +listType=map // +listMapKey=type - \ Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` - \n // other fields }" - properties: - lastTransitionTime: - description: lastTransitionTime is the last time the condition - transitioned from one status to another. This should be when - the underlying condition changed. If that is not known, then - using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: message is a human readable message indicating - details about the transition. This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: observedGeneration represents the .metadata.generation - that the condition was set based upon. For instance, if .metadata.generation - is currently 12, but the .status.conditions[x].observedGeneration - is 9, the condition is out of date with respect to the current - state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: reason contains a programmatic identifier indicating - the reason for the condition's last transition. Producers - of specific condition types may define expected values and - meanings for this field, and whether the values are considered - a guaranteed API. The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - --- Many .condition.type values are consistent across resources - like Available, but because arbitrary conditions can be useful - (see .node.status.conditions), the ability to deconflict is - important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - lastHandledReconcileAt: - description: LastHandledReconcileAt holds the value of the most recent - reconcile request value, so a change can be detected. - type: string - observedGeneration: - description: ObservedGeneration is the last observed generation. - format: int64 - type: integer - url: - description: URL is the download link for the last chart pulled. - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.5.0 - creationTimestamp: null - labels: - app.kubernetes.io/instance: flux-system - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v0.19.1 - name: helmreleases.helm.toolkit.fluxcd.io -spec: - group: helm.toolkit.fluxcd.io - names: - kind: HelmRelease - listKind: HelmReleaseList - plural: helmreleases - shortNames: - - hr - singular: helmrelease - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Status - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v2beta1 - schema: - openAPIV3Schema: - description: HelmRelease is the Schema for the helmreleases API - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: HelmReleaseSpec defines the desired state of a Helm release. - properties: - chart: - description: Chart defines the template of the v1beta1.HelmChart that - should be created for this HelmRelease. - properties: - spec: - description: Spec holds the template for the v1beta1.HelmChartSpec - for this HelmRelease. - properties: - chart: - description: The name or path the Helm chart is available - at in the SourceRef. - type: string - interval: - description: Interval at which to check the v1beta1.Source - for updates. Defaults to 'HelmReleaseSpec.Interval'. - type: string - reconcileStrategy: - default: ChartVersion - description: Determines what enables the creation of a new - artifact. Valid values are ('ChartVersion', 'Revision'). - See the documentation of the values for an explanation on - their behavior. Defaults to ChartVersion when omitted. - enum: - - ChartVersion - - Revision - type: string - sourceRef: - description: The name and namespace of the v1beta1.Source - the chart is available at. - properties: - apiVersion: - description: APIVersion of the referent. - type: string - kind: - description: Kind of the referent. - enum: - - HelmRepository - - GitRepository - - Bucket - type: string - name: - description: Name of the referent. - maxLength: 253 - minLength: 1 - type: string - namespace: - description: Namespace of the referent. - maxLength: 63 - minLength: 1 - type: string - required: - - name - type: object - valuesFile: - description: Alternative values file to use as the default - chart values, expected to be a relative path in the SourceRef. - Deprecated in favor of ValuesFiles, for backwards compatibility - the file defined here is merged before the ValuesFiles items. - Ignored when omitted. - type: string - valuesFiles: - description: Alternative list of values files to use as the - chart values (values.yaml is not included by default), expected - to be a relative path in the SourceRef. Values files are - merged in the order of this list with the last file overriding - the first. Ignored when omitted. - items: - type: string - type: array - version: - default: '*' - description: Version semver expression, ignored for charts - from v1beta1.GitRepository and v1beta1.Bucket sources. Defaults - to latest when omitted. - type: string - required: - - chart - - sourceRef - type: object - required: - - spec - type: object - dependsOn: - description: DependsOn may contain a dependency.CrossNamespaceDependencyReference - slice with references to HelmRelease resources that must be ready - before this HelmRelease can be reconciled. - items: - description: CrossNamespaceDependencyReference holds the reference - to a dependency. - properties: - name: - description: Name holds the name reference of a dependency. - type: string - namespace: - description: Namespace holds the namespace reference of a dependency. - type: string - required: - - name - type: object - type: array - install: - description: Install holds the configuration for Helm install actions - for this HelmRelease. - properties: - crds: - description: "CRDs upgrade CRDs from the Helm Chart's crds directory - according to the CRD upgrade policy provided here. Valid values - are `Skip`, `Create` or `CreateReplace`. Default is `Create` - and if omitted CRDs are installed but not updated. \n Skip: - do neither install nor replace (update) any CRDs. \n Create: - new CRDs are created, existing CRDs are neither updated nor - deleted. \n CreateReplace: new CRDs are created, existing CRDs - are updated (replaced) but not deleted. \n By default, CRDs - are applied (installed) during Helm install action. With this - option users can opt-in to CRD replace existing CRDs on Helm - install actions, which is not (yet) natively supported by Helm. - https://helm.sh/docs/chart_best_practices/custom_resource_definitions." - enum: - - Skip - - Create - - CreateReplace - type: string - createNamespace: - description: CreateNamespace tells the Helm install action to - create the HelmReleaseSpec.TargetNamespace if it does not exist - yet. On uninstall, the namespace will not be garbage collected. - type: boolean - disableHooks: - description: DisableHooks prevents hooks from running during the - Helm install action. - type: boolean - disableOpenAPIValidation: - description: DisableOpenAPIValidation prevents the Helm install - action from validating rendered templates against the Kubernetes - OpenAPI Schema. - type: boolean - disableWait: - description: DisableWait disables the waiting for resources to - be ready after a Helm install has been performed. - type: boolean - disableWaitForJobs: - description: DisableWaitForJobs disables waiting for jobs to complete - after a Helm install has been performed. - type: boolean - remediation: - description: Remediation holds the remediation configuration for - when the Helm install action for the HelmRelease fails. The - default is to not perform any action. - properties: - ignoreTestFailures: - description: IgnoreTestFailures tells the controller to skip - remediation when the Helm tests are run after an install - action but fail. Defaults to 'Test.IgnoreFailures'. - type: boolean - remediateLastFailure: - description: RemediateLastFailure tells the controller to - remediate the last failure, when no retries remain. Defaults - to 'false'. - type: boolean - retries: - description: Retries is the number of retries that should - be attempted on failures before bailing. Remediation, using - an uninstall, is performed between each attempt. Defaults - to '0', a negative integer equals to unlimited retries. - type: integer - type: object - replace: - description: Replace tells the Helm install action to re-use the - 'ReleaseName', but only if that name is a deleted release which - remains in the history. - type: boolean - skipCRDs: - description: "SkipCRDs tells the Helm install action to not install - any CRDs. By default, CRDs are installed if not already present. - \n Deprecated use CRD policy (`crds`) attribute with value `Skip` - instead." - type: boolean - timeout: - description: Timeout is the time to wait for any individual Kubernetes - operation (like Jobs for hooks) during the performance of a - Helm install action. Defaults to 'HelmReleaseSpec.Timeout'. - type: string - type: object - interval: - description: Interval at which to reconcile the Helm release. - type: string - kubeConfig: - description: KubeConfig for reconciling the HelmRelease on a remote - cluster. When specified, KubeConfig takes precedence over ServiceAccountName. - properties: - secretRef: - description: SecretRef holds the name to a secret that contains - a 'value' key with the kubeconfig file as the value. It must - be in the same namespace as the HelmRelease. It is recommended - that the kubeconfig is self-contained, and the secret is regularly - updated if credentials such as a cloud-access-token expire. - Cloud specific `cmd-path` auth helpers will not function without - adding binaries and credentials to the Pod that is responsible - for reconciling the HelmRelease. - properties: - name: - description: Name of the referent - type: string - required: - - name - type: object - type: object - maxHistory: - description: MaxHistory is the number of revisions saved by Helm for - this HelmRelease. Use '0' for an unlimited number of revisions; - defaults to '10'. - type: integer - postRenderers: - description: PostRenderers holds an array of Helm PostRenderers, which - will be applied in order of their definition. - items: - description: PostRenderer contains a Helm PostRenderer specification. - properties: - kustomize: - description: Kustomization to apply as PostRenderer. - properties: - images: - description: Images is a list of (image name, new name, - new tag or digest) for changing image names, tags or digests. - This can also be achieved with a patch, but this operator - is simpler to specify. - items: - description: Image contains an image name, a new name, - a new tag or digest, which will replace the original - name and tag. - properties: - digest: - description: Digest is the value used to replace the - original image tag. If digest is present NewTag - value is ignored. - type: string - name: - description: Name is a tag-less image name. - type: string - newName: - description: NewName is the value used to replace - the original name. - type: string - newTag: - description: NewTag is the value used to replace the - original tag. - type: string - required: - - name - type: object - type: array - patchesJson6902: - description: JSON 6902 patches, defined as inline YAML objects. - items: - description: JSON6902Patch contains a JSON6902 patch and - the target the patch should be applied to. - properties: - patch: - description: Patch contains the JSON6902 patch document - with an array of operation objects. - items: - description: JSON6902 is a JSON6902 operation object. - https://tools.ietf.org/html/rfc6902#section-4 - properties: - from: - type: string - op: - enum: - - test - - remove - - add - - replace - - move - - copy - type: string - path: - type: string - value: - x-kubernetes-preserve-unknown-fields: true - required: - - op - - path - type: object - type: array - target: - description: Target points to the resources that the - patch document should be applied to. - properties: - annotationSelector: - description: AnnotationSelector is a string that - follows the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api - It matches with the resource annotations. - type: string - group: - description: Group is the API group to select - resources from. Together with Version and Kind - it is capable of unambiguously identifying and/or - selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md - type: string - kind: - description: Kind of the API Group to select resources - from. Together with Group and Version it is - capable of unambiguously identifying and/or - selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md - type: string - labelSelector: - description: LabelSelector is a string that follows - the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api - It matches with the resource labels. - type: string - name: - description: Name to match resources with. - type: string - namespace: - description: Namespace to select resources from. - type: string - version: - description: Version of the API Group to select - resources from. Together with Group and Kind - it is capable of unambiguously identifying and/or - selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md - type: string - type: object - required: - - patch - - target - type: object - type: array - patchesStrategicMerge: - description: Strategic merge patches, defined as inline - YAML objects. - items: - x-kubernetes-preserve-unknown-fields: true - type: array - type: object - type: object - type: array - releaseName: - description: ReleaseName used for the Helm release. Defaults to a - composition of '[TargetNamespace-]Name'. - maxLength: 53 - minLength: 1 - type: string - rollback: - description: Rollback holds the configuration for Helm rollback actions - for this HelmRelease. - properties: - cleanupOnFail: - description: CleanupOnFail allows deletion of new resources created - during the Helm rollback action when it fails. - type: boolean - disableHooks: - description: DisableHooks prevents hooks from running during the - Helm rollback action. - type: boolean - disableWait: - description: DisableWait disables the waiting for resources to - be ready after a Helm rollback has been performed. - type: boolean - disableWaitForJobs: - description: DisableWaitForJobs disables waiting for jobs to complete - after a Helm rollback has been performed. - type: boolean - force: - description: Force forces resource updates through a replacement - strategy. - type: boolean - recreate: - description: Recreate performs pod restarts for the resource if - applicable. - type: boolean - timeout: - description: Timeout is the time to wait for any individual Kubernetes - operation (like Jobs for hooks) during the performance of a - Helm rollback action. Defaults to 'HelmReleaseSpec.Timeout'. - type: string - type: object - serviceAccountName: - description: The name of the Kubernetes service account to impersonate - when reconciling this HelmRelease. - type: string - storageNamespace: - description: StorageNamespace used for the Helm storage. Defaults - to the namespace of the HelmRelease. - maxLength: 63 - minLength: 1 - type: string - suspend: - description: Suspend tells the controller to suspend reconciliation - for this HelmRelease, it does not apply to already started reconciliations. - Defaults to false. - type: boolean - targetNamespace: - description: TargetNamespace to target when performing operations - for the HelmRelease. Defaults to the namespace of the HelmRelease. - maxLength: 63 - minLength: 1 - type: string - test: - description: Test holds the configuration for Helm test actions for - this HelmRelease. - properties: - enable: - description: Enable enables Helm test actions for this HelmRelease - after an Helm install or upgrade action has been performed. - type: boolean - ignoreFailures: - description: IgnoreFailures tells the controller to skip remediation - when the Helm tests are run but fail. Can be overwritten for - tests run after install or upgrade actions in 'Install.IgnoreTestFailures' - and 'Upgrade.IgnoreTestFailures'. - type: boolean - timeout: - description: Timeout is the time to wait for any individual Kubernetes - operation during the performance of a Helm test action. Defaults - to 'HelmReleaseSpec.Timeout'. - type: string - type: object - timeout: - description: Timeout is the time to wait for any individual Kubernetes - operation (like Jobs for hooks) during the performance of a Helm - action. Defaults to '5m0s'. - type: string - uninstall: - description: Uninstall holds the configuration for Helm uninstall - actions for this HelmRelease. - properties: - disableHooks: - description: DisableHooks prevents hooks from running during the - Helm rollback action. - type: boolean - keepHistory: - description: KeepHistory tells Helm to remove all associated resources - and mark the release as deleted, but retain the release history. - type: boolean - timeout: - description: Timeout is the time to wait for any individual Kubernetes - operation (like Jobs for hooks) during the performance of a - Helm uninstall action. Defaults to 'HelmReleaseSpec.Timeout'. - type: string - type: object - upgrade: - description: Upgrade holds the configuration for Helm upgrade actions - for this HelmRelease. - properties: - cleanupOnFail: - description: CleanupOnFail allows deletion of new resources created - during the Helm upgrade action when it fails. - type: boolean - crds: - description: "CRDs upgrade CRDs from the Helm Chart's crds directory - according to the CRD upgrade policy provided here. Valid values - are `Skip`, `Create` or `CreateReplace`. Default is `Skip` and - if omitted CRDs are neither installed nor upgraded. \n Skip: - do neither install nor replace (update) any CRDs. \n Create: - new CRDs are created, existing CRDs are neither updated nor - deleted. \n CreateReplace: new CRDs are created, existing CRDs - are updated (replaced) but not deleted. \n By default, CRDs - are not applied during Helm upgrade action. With this option - users can opt-in to CRD upgrade, which is not (yet) natively - supported by Helm. https://helm.sh/docs/chart_best_practices/custom_resource_definitions." - enum: - - Skip - - Create - - CreateReplace - type: string - disableHooks: - description: DisableHooks prevents hooks from running during the - Helm upgrade action. - type: boolean - disableOpenAPIValidation: - description: DisableOpenAPIValidation prevents the Helm upgrade - action from validating rendered templates against the Kubernetes - OpenAPI Schema. - type: boolean - disableWait: - description: DisableWait disables the waiting for resources to - be ready after a Helm upgrade has been performed. - type: boolean - disableWaitForJobs: - description: DisableWaitForJobs disables waiting for jobs to complete - after a Helm upgrade has been performed. - type: boolean - force: - description: Force forces resource updates through a replacement - strategy. - type: boolean - preserveValues: - description: PreserveValues will make Helm reuse the last release's - values and merge in overrides from 'Values'. Setting this flag - makes the HelmRelease non-declarative. - type: boolean - remediation: - description: Remediation holds the remediation configuration for - when the Helm upgrade action for the HelmRelease fails. The - default is to not perform any action. - properties: - ignoreTestFailures: - description: IgnoreTestFailures tells the controller to skip - remediation when the Helm tests are run after an upgrade - action but fail. Defaults to 'Test.IgnoreFailures'. - type: boolean - remediateLastFailure: - description: RemediateLastFailure tells the controller to - remediate the last failure, when no retries remain. Defaults - to 'false' unless 'Retries' is greater than 0. - type: boolean - retries: - description: Retries is the number of retries that should - be attempted on failures before bailing. Remediation, using - 'Strategy', is performed between each attempt. Defaults - to '0', a negative integer equals to unlimited retries. - type: integer - strategy: - description: Strategy to use for failure remediation. Defaults - to 'rollback'. - enum: - - rollback - - uninstall - type: string - type: object - timeout: - description: Timeout is the time to wait for any individual Kubernetes - operation (like Jobs for hooks) during the performance of a - Helm upgrade action. Defaults to 'HelmReleaseSpec.Timeout'. - type: string - type: object - values: - description: Values holds the values for this Helm release. - x-kubernetes-preserve-unknown-fields: true - valuesFrom: - description: ValuesFrom holds references to resources containing Helm - values for this HelmRelease, and information about how they should - be merged. - items: - description: ValuesReference contains a reference to a resource - containing Helm values, and optionally the key they can be found - at. - properties: - kind: - description: Kind of the values referent, valid values are ('Secret', - 'ConfigMap'). - enum: - - Secret - - ConfigMap - type: string - name: - description: Name of the values referent. Should reside in the - same namespace as the referring resource. - maxLength: 253 - minLength: 1 - type: string - optional: - description: Optional marks this ValuesReference as optional. - When set, a not found error for the values reference is ignored, - but any ValuesKey, TargetPath or transient error will still - result in a reconciliation failure. - type: boolean - targetPath: - description: TargetPath is the YAML dot notation path the value - should be merged at. When set, the ValuesKey is expected to - be a single flat value. Defaults to 'None', which results - in the values getting merged at the root. - type: string - valuesKey: - description: ValuesKey is the data key where the values.yaml - or a specific value can be found at. Defaults to 'values.yaml'. - type: string - required: - - kind - - name - type: object - type: array - required: - - chart - - interval - type: object - status: - default: - observedGeneration: -1 - description: HelmReleaseStatus defines the observed state of a HelmRelease. - properties: - conditions: - description: Conditions holds the conditions for the HelmRelease. - items: - description: "Condition contains details for one aspect of the current - state of this API Resource. --- This struct is intended for direct - use as an array at the field path .status.conditions. For example, - type FooStatus struct{ // Represents the observations of a - foo's current state. // Known .status.conditions.type are: - \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type - \ // +patchStrategy=merge // +listType=map // +listMapKey=type - \ Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` - \n // other fields }" - properties: - lastTransitionTime: - description: lastTransitionTime is the last time the condition - transitioned from one status to another. This should be when - the underlying condition changed. If that is not known, then - using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: message is a human readable message indicating - details about the transition. This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: observedGeneration represents the .metadata.generation - that the condition was set based upon. For instance, if .metadata.generation - is currently 12, but the .status.conditions[x].observedGeneration - is 9, the condition is out of date with respect to the current - state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: reason contains a programmatic identifier indicating - the reason for the condition's last transition. Producers - of specific condition types may define expected values and - meanings for this field, and whether the values are considered - a guaranteed API. The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - --- Many .condition.type values are consistent across resources - like Available, but because arbitrary conditions can be useful - (see .node.status.conditions), the ability to deconflict is - important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - failures: - description: Failures is the reconciliation failure count against - the latest desired state. It is reset after a successful reconciliation. - format: int64 - type: integer - helmChart: - description: HelmChart is the namespaced name of the HelmChart resource - created by the controller for the HelmRelease. - type: string - installFailures: - description: InstallFailures is the install failure count against - the latest desired state. It is reset after a successful reconciliation. - format: int64 - type: integer - lastAppliedRevision: - description: LastAppliedRevision is the revision of the last successfully - applied source. - type: string - lastAttemptedRevision: - description: LastAttemptedRevision is the revision of the last reconciliation - attempt. - type: string - lastAttemptedValuesChecksum: - description: LastAttemptedValuesChecksum is the SHA1 checksum of the - values of the last reconciliation attempt. - type: string - lastHandledReconcileAt: - description: LastHandledReconcileAt holds the value of the most recent - reconcile request value, so a change can be detected. - type: string - lastReleaseRevision: - description: LastReleaseRevision is the revision of the last successful - Helm release. - type: integer - observedGeneration: - description: ObservedGeneration is the last observed generation. - format: int64 - type: integer - upgradeFailures: - description: UpgradeFailures is the upgrade failure count against - the latest desired state. It is reset after a successful reconciliation. - format: int64 - type: integer - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.5.0 - creationTimestamp: null - labels: - app.kubernetes.io/instance: flux-system - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v0.19.1 - name: helmrepositories.source.toolkit.fluxcd.io -spec: - group: source.toolkit.fluxcd.io - names: - kind: HelmRepository - listKind: HelmRepositoryList - plural: helmrepositories - shortNames: - - helmrepo - singular: helmrepository - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .spec.url - name: URL - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Status - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1beta1 - schema: - openAPIV3Schema: - description: HelmRepository is the Schema for the helmrepositories API - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: HelmRepositorySpec defines the reference to a Helm repository. - properties: - interval: - description: The interval at which to check the upstream for updates. - type: string - passCredentials: - description: PassCredentials allows the credentials from the SecretRef - to be passed on to a host that does not match the host as defined - in URL. This may be required if the host of the advertised chart - URLs in the index differ from the defined URL. Enabling this should - be done with caution, as it can potentially result in credentials - getting stolen in a MITM-attack. - type: boolean - secretRef: - description: The name of the secret containing authentication credentials - for the Helm repository. For HTTP/S basic auth the secret must contain - username and password fields. For TLS the secret must contain a - certFile and keyFile, and/or caCert fields. - properties: - name: - description: Name of the referent - type: string - required: - - name - type: object - suspend: - description: This flag tells the controller to suspend the reconciliation - of this source. - type: boolean - timeout: - default: 60s - description: The timeout of index downloading, defaults to 60s. - type: string - url: - description: The Helm repository URL, a valid URL contains at least - a protocol and host. - type: string - required: - - interval - - url - type: object - status: - description: HelmRepositoryStatus defines the observed state of the HelmRepository. - properties: - artifact: - description: Artifact represents the output of the last successful - repository sync. - properties: - checksum: - description: Checksum is the SHA1 checksum of the artifact. - type: string - lastUpdateTime: - description: LastUpdateTime is the timestamp corresponding to - the last update of this artifact. - format: date-time - type: string - path: - description: Path is the relative file path of this artifact. - type: string - revision: - description: Revision is a human readable identifier traceable - in the origin source system. It can be a Git commit SHA, Git - tag, a Helm index timestamp, a Helm chart version, etc. - type: string - url: - description: URL is the HTTP address of this artifact. - type: string - required: - - path - - url - type: object - conditions: - description: Conditions holds the conditions for the HelmRepository. - items: - description: "Condition contains details for one aspect of the current - state of this API Resource. --- This struct is intended for direct - use as an array at the field path .status.conditions. For example, - type FooStatus struct{ // Represents the observations of a - foo's current state. // Known .status.conditions.type are: - \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type - \ // +patchStrategy=merge // +listType=map // +listMapKey=type - \ Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` - \n // other fields }" - properties: - lastTransitionTime: - description: lastTransitionTime is the last time the condition - transitioned from one status to another. This should be when - the underlying condition changed. If that is not known, then - using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: message is a human readable message indicating - details about the transition. This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: observedGeneration represents the .metadata.generation - that the condition was set based upon. For instance, if .metadata.generation - is currently 12, but the .status.conditions[x].observedGeneration - is 9, the condition is out of date with respect to the current - state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: reason contains a programmatic identifier indicating - the reason for the condition's last transition. Producers - of specific condition types may define expected values and - meanings for this field, and whether the values are considered - a guaranteed API. The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - --- Many .condition.type values are consistent across resources - like Available, but because arbitrary conditions can be useful - (see .node.status.conditions), the ability to deconflict is - important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - lastHandledReconcileAt: - description: LastHandledReconcileAt holds the value of the most recent - reconcile request value, so a change can be detected. - type: string - observedGeneration: - description: ObservedGeneration is the last observed generation. - format: int64 - type: integer - url: - description: URL is the download link for the last index fetched. - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.5.0 - creationTimestamp: null - labels: - app.kubernetes.io/instance: flux-system - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v0.19.1 - name: kustomizations.kustomize.toolkit.fluxcd.io -spec: - group: kustomize.toolkit.fluxcd.io - names: - kind: Kustomization - listKind: KustomizationList - plural: kustomizations - shortNames: - - ks - singular: kustomization - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Status - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1beta1 - schema: - openAPIV3Schema: - description: Kustomization is the Schema for the kustomizations API. - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: KustomizationSpec defines the desired state of a kustomization. - properties: - decryption: - description: Decrypt Kubernetes secrets before applying them on the - cluster. - properties: - provider: - description: Provider is the name of the decryption engine. - enum: - - sops - type: string - secretRef: - description: The secret name containing the private OpenPGP keys - used for decryption. - properties: - name: - description: Name of the referent - type: string - required: - - name - type: object - required: - - provider - type: object - dependsOn: - description: DependsOn may contain a dependency.CrossNamespaceDependencyReference - slice with references to Kustomization resources that must be ready - before this Kustomization can be reconciled. - items: - description: CrossNamespaceDependencyReference holds the reference - to a dependency. - properties: - name: - description: Name holds the name reference of a dependency. - type: string - namespace: - description: Namespace holds the namespace reference of a dependency. - type: string - required: - - name - type: object - type: array - force: - default: false - description: Force instructs the controller to recreate resources - when patching fails due to an immutable field change. - type: boolean - healthChecks: - description: A list of resources to be included in the health assessment. - items: - description: NamespacedObjectKindReference contains enough information - to let you locate the typed referenced object in any namespace - properties: - apiVersion: - description: API version of the referent, if not specified the - Kubernetes preferred version will be used - type: string - kind: - description: Kind of the referent - type: string - name: - description: Name of the referent - type: string - namespace: - description: Namespace of the referent, when not specified it - acts as LocalObjectReference - type: string - required: - - kind - - name - type: object - type: array - images: - description: Images is a list of (image name, new name, new tag or - digest) for changing image names, tags or digests. This can also - be achieved with a patch, but this operator is simpler to specify. - items: - description: Image contains an image name, a new name, a new tag - or digest, which will replace the original name and tag. - properties: - digest: - description: Digest is the value used to replace the original - image tag. If digest is present NewTag value is ignored. - type: string - name: - description: Name is a tag-less image name. - type: string - newName: - description: NewName is the value used to replace the original - name. - type: string - newTag: - description: NewTag is the value used to replace the original - tag. - type: string - required: - - name - type: object - type: array - interval: - description: The interval at which to reconcile the Kustomization. - type: string - kubeConfig: - description: The KubeConfig for reconciling the Kustomization on a - remote cluster. When specified, KubeConfig takes precedence over - ServiceAccountName. - properties: - secretRef: - description: SecretRef holds the name to a secret that contains - a 'value' key with the kubeconfig file as the value. It must - be in the same namespace as the Kustomization. It is recommended - that the kubeconfig is self-contained, and the secret is regularly - updated if credentials such as a cloud-access-token expire. - Cloud specific `cmd-path` auth helpers will not function without - adding binaries and credentials to the Pod that is responsible - for reconciling the Kustomization. - properties: - name: - description: Name of the referent - type: string - required: - - name - type: object - type: object - patches: - description: Strategic merge and JSON patches, defined as inline YAML - objects, capable of targeting objects based on kind, label and annotation - selectors. - items: - description: Patch contains either a StrategicMerge or a JSON6902 - patch, either a file or inline, and the target the patch should - be applied to. - properties: - patch: - description: Patch contains the JSON6902 patch document with - an array of operation objects. - type: string - target: - description: Target points to the resources that the patch document - should be applied to. - properties: - annotationSelector: - description: AnnotationSelector is a string that follows - the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api - It matches with the resource annotations. - type: string - group: - description: Group is the API group to select resources - from. Together with Version and Kind it is capable of - unambiguously identifying and/or selecting resources. - https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md - type: string - kind: - description: Kind of the API Group to select resources from. - Together with Group and Version it is capable of unambiguously - identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md - type: string - labelSelector: - description: LabelSelector is a string that follows the - label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api - It matches with the resource labels. - type: string - name: - description: Name to match resources with. - type: string - namespace: - description: Namespace to select resources from. - type: string - version: - description: Version of the API Group to select resources - from. Together with Group and Kind it is capable of unambiguously - identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md - type: string - type: object - type: object - type: array - patchesJson6902: - description: JSON 6902 patches, defined as inline YAML objects. - items: - description: JSON6902Patch contains a JSON6902 patch and the target - the patch should be applied to. - properties: - patch: - description: Patch contains the JSON6902 patch document with - an array of operation objects. - items: - description: JSON6902 is a JSON6902 operation object. https://tools.ietf.org/html/rfc6902#section-4 - properties: - from: - type: string - op: - enum: - - test - - remove - - add - - replace - - move - - copy - type: string - path: - type: string - value: - x-kubernetes-preserve-unknown-fields: true - required: - - op - - path - type: object - type: array - target: - description: Target points to the resources that the patch document - should be applied to. - properties: - annotationSelector: - description: AnnotationSelector is a string that follows - the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api - It matches with the resource annotations. - type: string - group: - description: Group is the API group to select resources - from. Together with Version and Kind it is capable of - unambiguously identifying and/or selecting resources. - https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md - type: string - kind: - description: Kind of the API Group to select resources from. - Together with Group and Version it is capable of unambiguously - identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md - type: string - labelSelector: - description: LabelSelector is a string that follows the - label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api - It matches with the resource labels. - type: string - name: - description: Name to match resources with. - type: string - namespace: - description: Namespace to select resources from. - type: string - version: - description: Version of the API Group to select resources - from. Together with Group and Kind it is capable of unambiguously - identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md - type: string - type: object - required: - - patch - - target - type: object - type: array - patchesStrategicMerge: - description: Strategic merge patches, defined as inline YAML objects. - items: - x-kubernetes-preserve-unknown-fields: true - type: array - path: - description: Path to the directory containing the kustomization.yaml - file, or the set of plain YAMLs a kustomization.yaml should be generated - for. Defaults to 'None', which translates to the root path of the - SourceRef. - type: string - postBuild: - description: PostBuild describes which actions to perform on the YAML - manifest generated by building the kustomize overlay. - properties: - substitute: - additionalProperties: - type: string - description: Substitute holds a map of key/value pairs. The variables - defined in your YAML manifests that match any of the keys defined - in the map will be substituted with the set value. Includes - support for bash string replacement functions e.g. ${var:=default}, - ${var:position} and ${var/substring/replacement}. - type: object - substituteFrom: - description: SubstituteFrom holds references to ConfigMaps and - Secrets containing the variables and their values to be substituted - in the YAML manifests. The ConfigMap and the Secret data keys - represent the var names and they must match the vars declared - in the manifests for the substitution to happen. - items: - description: SubstituteReference contains a reference to a resource - containing the variables name and value. - properties: - kind: - description: Kind of the values referent, valid values are - ('Secret', 'ConfigMap'). - enum: - - Secret - - ConfigMap - type: string - name: - description: Name of the values referent. Should reside - in the same namespace as the referring resource. - maxLength: 253 - minLength: 1 - type: string - required: - - kind - - name - type: object - type: array - type: object - prune: - description: Prune enables garbage collection. - type: boolean - retryInterval: - description: The interval at which to retry a previously failed reconciliation. - When not specified, the controller uses the KustomizationSpec.Interval - value to retry failures. - type: string - serviceAccountName: - description: The name of the Kubernetes service account to impersonate - when reconciling this Kustomization. - type: string - sourceRef: - description: Reference of the source where the kustomization file - is. - properties: - apiVersion: - description: API version of the referent - type: string - kind: - description: Kind of the referent - enum: - - GitRepository - - Bucket - type: string - name: - description: Name of the referent - type: string - namespace: - description: Namespace of the referent, defaults to the Kustomization - namespace - type: string - required: - - kind - - name - type: object - suspend: - description: This flag tells the controller to suspend subsequent - kustomize executions, it does not apply to already started executions. - Defaults to false. - type: boolean - targetNamespace: - description: TargetNamespace sets or overrides the namespace in the - kustomization.yaml file. - maxLength: 63 - minLength: 1 - type: string - timeout: - description: Timeout for validation, apply and health checking operations. - Defaults to 'Interval' duration. - type: string - validation: - description: Validate the Kubernetes objects before applying them - on the cluster. The validation strategy can be 'client' (local dry-run), - 'server' (APIServer dry-run) or 'none'. When 'Force' is 'true', - validation will fallback to 'client' if set to 'server' because - server-side validation is not supported in this scenario. - enum: - - none - - client - - server - type: string - required: - - interval - - prune - - sourceRef - type: object - status: - default: - observedGeneration: -1 - description: KustomizationStatus defines the observed state of a kustomization. - properties: - conditions: - items: - description: "Condition contains details for one aspect of the current - state of this API Resource. --- This struct is intended for direct - use as an array at the field path .status.conditions. For example, - type FooStatus struct{ // Represents the observations of a - foo's current state. // Known .status.conditions.type are: - \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type - \ // +patchStrategy=merge // +listType=map // +listMapKey=type - \ Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` - \n // other fields }" - properties: - lastTransitionTime: - description: lastTransitionTime is the last time the condition - transitioned from one status to another. This should be when - the underlying condition changed. If that is not known, then - using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: message is a human readable message indicating - details about the transition. This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: observedGeneration represents the .metadata.generation - that the condition was set based upon. For instance, if .metadata.generation - is currently 12, but the .status.conditions[x].observedGeneration - is 9, the condition is out of date with respect to the current - state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: reason contains a programmatic identifier indicating - the reason for the condition's last transition. Producers - of specific condition types may define expected values and - meanings for this field, and whether the values are considered - a guaranteed API. The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - --- Many .condition.type values are consistent across resources - like Available, but because arbitrary conditions can be useful - (see .node.status.conditions), the ability to deconflict is - important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - lastAppliedRevision: - description: The last successfully applied revision. The revision - format for Git sources is /. - type: string - lastAttemptedRevision: - description: LastAttemptedRevision is the revision of the last reconciliation - attempt. - type: string - lastHandledReconcileAt: - description: LastHandledReconcileAt holds the value of the most recent - reconcile request value, so a change can be detected. - type: string - observedGeneration: - description: ObservedGeneration is the last reconciled generation. - format: int64 - type: integer - snapshot: - description: The last successfully applied revision metadata. - properties: - checksum: - description: The manifests sha1 checksum. - type: string - entries: - description: A list of Kubernetes kinds grouped by namespace. - items: - description: Snapshot holds the metadata of namespaced Kubernetes - objects - properties: - kinds: - additionalProperties: - type: string - description: The list of Kubernetes kinds. - type: object - namespace: - description: The namespace of this entry. - type: string - required: - - kinds - type: object - type: array - required: - - checksum - - entries - type: object - type: object - type: object - served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Status - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1beta2 - schema: - openAPIV3Schema: - description: Kustomization is the Schema for the kustomizations API. - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: KustomizationSpec defines the configuration to calculate - the desired state from a Source using Kustomize. - properties: - decryption: - description: Decrypt Kubernetes secrets before applying them on the - cluster. - properties: - provider: - description: Provider is the name of the decryption engine. - enum: - - sops - type: string - secretRef: - description: The secret name containing the private OpenPGP keys - used for decryption. - properties: - name: - description: Name of the referent - type: string - required: - - name - type: object - required: - - provider - type: object - dependsOn: - description: DependsOn may contain a dependency.CrossNamespaceDependencyReference - slice with references to Kustomization resources that must be ready - before this Kustomization can be reconciled. - items: - description: CrossNamespaceDependencyReference holds the reference - to a dependency. - properties: - name: - description: Name holds the name reference of a dependency. - type: string - namespace: - description: Namespace holds the namespace reference of a dependency. - type: string - required: - - name - type: object - type: array - force: - default: false - description: Force instructs the controller to recreate resources - when patching fails due to an immutable field change. - type: boolean - healthChecks: - description: A list of resources to be included in the health assessment. - items: - description: NamespacedObjectKindReference contains enough information - to let you locate the typed referenced object in any namespace - properties: - apiVersion: - description: API version of the referent, if not specified the - Kubernetes preferred version will be used - type: string - kind: - description: Kind of the referent - type: string - name: - description: Name of the referent - type: string - namespace: - description: Namespace of the referent, when not specified it - acts as LocalObjectReference - type: string - required: - - kind - - name - type: object - type: array - images: - description: Images is a list of (image name, new name, new tag or - digest) for changing image names, tags or digests. This can also - be achieved with a patch, but this operator is simpler to specify. - items: - description: Image contains an image name, a new name, a new tag - or digest, which will replace the original name and tag. - properties: - digest: - description: Digest is the value used to replace the original - image tag. If digest is present NewTag value is ignored. - type: string - name: - description: Name is a tag-less image name. - type: string - newName: - description: NewName is the value used to replace the original - name. - type: string - newTag: - description: NewTag is the value used to replace the original - tag. - type: string - required: - - name - type: object - type: array - interval: - description: The interval at which to reconcile the Kustomization. - type: string - kubeConfig: - description: The KubeConfig for reconciling the Kustomization on a - remote cluster. When specified, KubeConfig takes precedence over - ServiceAccountName. - properties: - secretRef: - description: SecretRef holds the name to a secret that contains - a 'value' key with the kubeconfig file as the value. It must - be in the same namespace as the Kustomization. It is recommended - that the kubeconfig is self-contained, and the secret is regularly - updated if credentials such as a cloud-access-token expire. - Cloud specific `cmd-path` auth helpers will not function without - adding binaries and credentials to the Pod that is responsible - for reconciling the Kustomization. - properties: - name: - description: Name of the referent - type: string - required: - - name - type: object - type: object - patches: - description: Strategic merge and JSON patches, defined as inline YAML - objects, capable of targeting objects based on kind, label and annotation - selectors. - items: - description: Patch contains either a StrategicMerge or a JSON6902 - patch, either a file or inline, and the target the patch should - be applied to. - properties: - patch: - description: Patch contains the JSON6902 patch document with - an array of operation objects. - type: string - target: - description: Target points to the resources that the patch document - should be applied to. - properties: - annotationSelector: - description: AnnotationSelector is a string that follows - the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api - It matches with the resource annotations. - type: string - group: - description: Group is the API group to select resources - from. Together with Version and Kind it is capable of - unambiguously identifying and/or selecting resources. - https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md - type: string - kind: - description: Kind of the API Group to select resources from. - Together with Group and Version it is capable of unambiguously - identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md - type: string - labelSelector: - description: LabelSelector is a string that follows the - label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api - It matches with the resource labels. - type: string - name: - description: Name to match resources with. - type: string - namespace: - description: Namespace to select resources from. - type: string - version: - description: Version of the API Group to select resources - from. Together with Group and Kind it is capable of unambiguously - identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md - type: string - type: object - type: object - type: array - patchesJson6902: - description: 'JSON 6902 patches, defined as inline YAML objects. Deprecated: - Use Patches instead.' - items: - description: JSON6902Patch contains a JSON6902 patch and the target - the patch should be applied to. - properties: - patch: - description: Patch contains the JSON6902 patch document with - an array of operation objects. - items: - description: JSON6902 is a JSON6902 operation object. https://tools.ietf.org/html/rfc6902#section-4 - properties: - from: - type: string - op: - enum: - - test - - remove - - add - - replace - - move - - copy - type: string - path: - type: string - value: - x-kubernetes-preserve-unknown-fields: true - required: - - op - - path - type: object - type: array - target: - description: Target points to the resources that the patch document - should be applied to. - properties: - annotationSelector: - description: AnnotationSelector is a string that follows - the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api - It matches with the resource annotations. - type: string - group: - description: Group is the API group to select resources - from. Together with Version and Kind it is capable of - unambiguously identifying and/or selecting resources. - https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md - type: string - kind: - description: Kind of the API Group to select resources from. - Together with Group and Version it is capable of unambiguously - identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md - type: string - labelSelector: - description: LabelSelector is a string that follows the - label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api - It matches with the resource labels. - type: string - name: - description: Name to match resources with. - type: string - namespace: - description: Namespace to select resources from. - type: string - version: - description: Version of the API Group to select resources - from. Together with Group and Kind it is capable of unambiguously - identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md - type: string - type: object - required: - - patch - - target - type: object - type: array - patchesStrategicMerge: - description: 'Strategic merge patches, defined as inline YAML objects. - Deprecated: Use Patches instead.' - items: - x-kubernetes-preserve-unknown-fields: true - type: array - path: - description: Path to the directory containing the kustomization.yaml - file, or the set of plain YAMLs a kustomization.yaml should be generated - for. Defaults to 'None', which translates to the root path of the - SourceRef. - type: string - postBuild: - description: PostBuild describes which actions to perform on the YAML - manifest generated by building the kustomize overlay. - properties: - substitute: - additionalProperties: - type: string - description: Substitute holds a map of key/value pairs. The variables - defined in your YAML manifests that match any of the keys defined - in the map will be substituted with the set value. Includes - support for bash string replacement functions e.g. ${var:=default}, - ${var:position} and ${var/substring/replacement}. - type: object - substituteFrom: - description: SubstituteFrom holds references to ConfigMaps and - Secrets containing the variables and their values to be substituted - in the YAML manifests. The ConfigMap and the Secret data keys - represent the var names and they must match the vars declared - in the manifests for the substitution to happen. - items: - description: SubstituteReference contains a reference to a resource - containing the variables name and value. - properties: - kind: - description: Kind of the values referent, valid values are - ('Secret', 'ConfigMap'). - enum: - - Secret - - ConfigMap - type: string - name: - description: Name of the values referent. Should reside - in the same namespace as the referring resource. - maxLength: 253 - minLength: 1 - type: string - required: - - kind - - name - type: object - type: array - type: object - prune: - description: Prune enables garbage collection. - type: boolean - retryInterval: - description: The interval at which to retry a previously failed reconciliation. - When not specified, the controller uses the KustomizationSpec.Interval - value to retry failures. - type: string - serviceAccountName: - description: The name of the Kubernetes service account to impersonate - when reconciling this Kustomization. - type: string - sourceRef: - description: Reference of the source where the kustomization file - is. - properties: - apiVersion: - description: API version of the referent. - type: string - kind: - description: Kind of the referent. - enum: - - GitRepository - - Bucket - type: string - name: - description: Name of the referent. - type: string - namespace: - description: Namespace of the referent, defaults to the namespace - of the Kubernetes resource object that contains the reference. - type: string - required: - - kind - - name - type: object - suspend: - description: This flag tells the controller to suspend subsequent - kustomize executions, it does not apply to already started executions. - Defaults to false. - type: boolean - targetNamespace: - description: TargetNamespace sets or overrides the namespace in the - kustomization.yaml file. - maxLength: 63 - minLength: 1 - type: string - timeout: - description: Timeout for validation, apply and health checking operations. - Defaults to 'Interval' duration. - type: string - validation: - description: 'Deprecated: Not used in v1beta2.' - enum: - - none - - client - - server - type: string - wait: - description: Wait instructs the controller to check the health of - all the reconciled resources. When enabled, the HealthChecks are - ignored. Defaults to false. - type: boolean - required: - - interval - - prune - - sourceRef - type: object - status: - default: - observedGeneration: -1 - description: KustomizationStatus defines the observed state of a kustomization. - properties: - conditions: - items: - description: "Condition contains details for one aspect of the current - state of this API Resource. --- This struct is intended for direct - use as an array at the field path .status.conditions. For example, - type FooStatus struct{ // Represents the observations of a - foo's current state. // Known .status.conditions.type are: - \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type - \ // +patchStrategy=merge // +listType=map // +listMapKey=type - \ Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` - \n // other fields }" - properties: - lastTransitionTime: - description: lastTransitionTime is the last time the condition - transitioned from one status to another. This should be when - the underlying condition changed. If that is not known, then - using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: message is a human readable message indicating - details about the transition. This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: observedGeneration represents the .metadata.generation - that the condition was set based upon. For instance, if .metadata.generation - is currently 12, but the .status.conditions[x].observedGeneration - is 9, the condition is out of date with respect to the current - state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: reason contains a programmatic identifier indicating - the reason for the condition's last transition. Producers - of specific condition types may define expected values and - meanings for this field, and whether the values are considered - a guaranteed API. The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - --- Many .condition.type values are consistent across resources - like Available, but because arbitrary conditions can be useful - (see .node.status.conditions), the ability to deconflict is - important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - inventory: - description: Inventory contains the list of Kubernetes resource object - references that have been successfully applied. - properties: - entries: - description: Entries of Kubernetes resource object references. - items: - description: ResourceRef contains the information necessary - to locate a resource within a cluster. - properties: - id: - description: ID is the string representation of the Kubernetes - resource object's metadata, in the format '___'. - type: string - v: - description: Version is the API version of the Kubernetes - resource object's kind. - type: string - required: - - id - - v - type: object - type: array - required: - - entries - type: object - lastAppliedRevision: - description: The last successfully applied revision. The revision - format for Git sources is /. - type: string - lastAttemptedRevision: - description: LastAttemptedRevision is the revision of the last reconciliation - attempt. - type: string - lastHandledReconcileAt: - description: LastHandledReconcileAt holds the value of the most recent - reconcile request value, so a change can be detected. - type: string - observedGeneration: - description: ObservedGeneration is the last reconciled generation. - format: int64 - type: integer - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.5.0 - creationTimestamp: null - labels: - app.kubernetes.io/instance: flux-system - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v0.19.1 - name: providers.notification.toolkit.fluxcd.io -spec: - group: notification.toolkit.fluxcd.io - names: - kind: Provider - listKind: ProviderList - plural: providers - singular: provider - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Status - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1beta1 - schema: - openAPIV3Schema: - description: Provider is the Schema for the providers API - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: ProviderSpec defines the desired state of Provider - properties: - address: - description: HTTP/S webhook address of this provider - pattern: ^(http|https):// - type: string - certSecretRef: - description: CertSecretRef can be given the name of a secret containing - a PEM-encoded CA certificate (`caFile`) - properties: - name: - description: Name of the referent - type: string - required: - - name - type: object - channel: - description: Alert channel for this provider - type: string - proxy: - description: HTTP/S address of the proxy - pattern: ^(http|https):// - type: string - secretRef: - description: Secret reference containing the provider webhook URL - using "address" as data key - properties: - name: - description: Name of the referent - type: string - required: - - name - type: object - type: - description: Type of provider - enum: - - slack - - discord - - msteams - - rocket - - generic - - github - - gitlab - - bitbucket - - azuredevops - - googlechat - - webex - - sentry - - azureeventhub - - telegram - - lark - - matrix - - opsgenie - - alertmanager - type: string - username: - description: Bot username for this provider - type: string - required: - - type - type: object - status: - default: - observedGeneration: -1 - description: ProviderStatus defines the observed state of Provider - properties: - conditions: - items: - description: "Condition contains details for one aspect of the current - state of this API Resource. --- This struct is intended for direct - use as an array at the field path .status.conditions. For example, - type FooStatus struct{ // Represents the observations of a - foo's current state. // Known .status.conditions.type are: - \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type - \ // +patchStrategy=merge // +listType=map // +listMapKey=type - \ Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` - \n // other fields }" - properties: - lastTransitionTime: - description: lastTransitionTime is the last time the condition - transitioned from one status to another. This should be when - the underlying condition changed. If that is not known, then - using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: message is a human readable message indicating - details about the transition. This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: observedGeneration represents the .metadata.generation - that the condition was set based upon. For instance, if .metadata.generation - is currently 12, but the .status.conditions[x].observedGeneration - is 9, the condition is out of date with respect to the current - state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: reason contains a programmatic identifier indicating - the reason for the condition's last transition. Producers - of specific condition types may define expected values and - meanings for this field, and whether the values are considered - a guaranteed API. The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - --- Many .condition.type values are consistent across resources - like Available, but because arbitrary conditions can be useful - (see .node.status.conditions), the ability to deconflict is - important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - observedGeneration: - description: ObservedGeneration is the last reconciled generation. - format: int64 - type: integer - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.5.0 - creationTimestamp: null - labels: - app.kubernetes.io/instance: flux-system - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v0.19.1 - name: receivers.notification.toolkit.fluxcd.io -spec: - group: notification.toolkit.fluxcd.io - names: - kind: Receiver - listKind: ReceiverList - plural: receivers - singular: receiver - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - - jsonPath: .status.conditions[?(@.type=="Ready")].message - name: Status - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1beta1 - schema: - openAPIV3Schema: - description: Receiver is the Schema for the receivers API - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: ReceiverSpec defines the desired state of Receiver - properties: - events: - description: A list of events to handle, e.g. 'push' for GitHub or - 'Push Hook' for GitLab. - items: - type: string - type: array - resources: - description: A list of resources to be notified about changes. - items: - description: CrossNamespaceObjectReference contains enough information - to let you locate the typed referenced object at cluster level - properties: - apiVersion: - description: API version of the referent - type: string - kind: - description: Kind of the referent - enum: - - Bucket - - GitRepository - - Kustomization - - HelmRelease - - HelmChart - - HelmRepository - - ImageRepository - - ImagePolicy - - ImageUpdateAutomation - type: string - name: - description: Name of the referent - maxLength: 53 - minLength: 1 - type: string - namespace: - description: Namespace of the referent - maxLength: 53 - minLength: 1 - type: string - required: - - name - type: object - type: array - secretRef: - description: Secret reference containing the token used to validate - the payload authenticity - properties: - name: - description: Name of the referent - type: string - required: - - name - type: object - suspend: - description: This flag tells the controller to suspend subsequent - events handling. Defaults to false. - type: boolean - type: - description: Type of webhook sender, used to determine the validation - procedure and payload deserialization. - enum: - - generic - - generic-hmac - - github - - gitlab - - bitbucket - - harbor - - dockerhub - - quay - - gcr - - nexus - - acr - type: string - required: - - resources - - type - type: object - status: - default: - observedGeneration: -1 - description: ReceiverStatus defines the observed state of Receiver - properties: - conditions: - items: - description: "Condition contains details for one aspect of the current - state of this API Resource. --- This struct is intended for direct - use as an array at the field path .status.conditions. For example, - type FooStatus struct{ // Represents the observations of a - foo's current state. // Known .status.conditions.type are: - \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type - \ // +patchStrategy=merge // +listType=map // +listMapKey=type - \ Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` - \n // other fields }" - properties: - lastTransitionTime: - description: lastTransitionTime is the last time the condition - transitioned from one status to another. This should be when - the underlying condition changed. If that is not known, then - using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: message is a human readable message indicating - details about the transition. This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: observedGeneration represents the .metadata.generation - that the condition was set based upon. For instance, if .metadata.generation - is currently 12, but the .status.conditions[x].observedGeneration - is 9, the condition is out of date with respect to the current - state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: reason contains a programmatic identifier indicating - the reason for the condition's last transition. Producers - of specific condition types may define expected values and - meanings for this field, and whether the values are considered - a guaranteed API. The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - --- Many .condition.type values are consistent across resources - like Available, but because arbitrary conditions can be useful - (see .node.status.conditions), the ability to deconflict is - important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - observedGeneration: - description: ObservedGeneration is the last observed generation. - format: int64 - type: integer - url: - description: Generated webhook URL in the format of '/hook/sha256sum(token+name+namespace)'. - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - labels: - app.kubernetes.io/instance: flux-system - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v0.19.1 - name: helm-controller - namespace: flux-system ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - labels: - app.kubernetes.io/instance: flux-system - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v0.19.1 - name: kustomize-controller - namespace: flux-system ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - labels: - app.kubernetes.io/instance: flux-system - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v0.19.1 - name: notification-controller - namespace: flux-system ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - labels: - app.kubernetes.io/instance: flux-system - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v0.19.1 - name: source-controller - namespace: flux-system ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - labels: - app.kubernetes.io/instance: flux-system - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v0.19.1 - name: crd-controller-flux-system -rules: -- apiGroups: - - source.toolkit.fluxcd.io - resources: - - '*' - verbs: - - '*' -- apiGroups: - - kustomize.toolkit.fluxcd.io - resources: - - '*' - verbs: - - '*' -- apiGroups: - - helm.toolkit.fluxcd.io - resources: - - '*' - verbs: - - '*' -- apiGroups: - - notification.toolkit.fluxcd.io - resources: - - '*' - verbs: - - '*' -- apiGroups: - - image.toolkit.fluxcd.io - resources: - - '*' - verbs: - - '*' -- apiGroups: - - "" - resources: - - namespaces - - secrets - verbs: - - get - - list - - watch -- apiGroups: - - "" - resources: - - events - verbs: - - create - - patch -- apiGroups: - - "" - resources: - - configmaps - - configmaps/status - verbs: - - get - - list - - watch - - create - - update - - patch - - delete -- apiGroups: - - coordination.k8s.io - resources: - - leases - verbs: - - get - - list - - watch - - create - - update - - patch - - delete ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - labels: - app.kubernetes.io/instance: flux-system - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v0.19.1 - name: cluster-reconciler-flux-system -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cluster-admin -subjects: -- kind: ServiceAccount - name: kustomize-controller - namespace: flux-system -- kind: ServiceAccount - name: helm-controller - namespace: flux-system ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - labels: - app.kubernetes.io/instance: flux-system - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v0.19.1 - name: crd-controller-flux-system -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: crd-controller-flux-system -subjects: -- kind: ServiceAccount - name: kustomize-controller - namespace: flux-system -- kind: ServiceAccount - name: helm-controller - namespace: flux-system -- kind: ServiceAccount - name: source-controller - namespace: flux-system -- kind: ServiceAccount - name: notification-controller - namespace: flux-system -- kind: ServiceAccount - name: image-reflector-controller - namespace: flux-system -- kind: ServiceAccount - name: image-automation-controller - namespace: flux-system ---- -apiVersion: v1 -kind: Service -metadata: - labels: - app.kubernetes.io/instance: flux-system - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v0.19.1 - control-plane: controller - name: notification-controller - namespace: flux-system -spec: - ports: - - name: http - port: 80 - protocol: TCP - targetPort: http - selector: - app: notification-controller - type: ClusterIP ---- -apiVersion: v1 -kind: Service -metadata: - labels: - app.kubernetes.io/instance: flux-system - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v0.19.1 - control-plane: controller - name: source-controller - namespace: flux-system -spec: - ports: - - name: http - port: 80 - protocol: TCP - targetPort: http - selector: - app: source-controller - type: ClusterIP ---- -apiVersion: v1 -kind: Service -metadata: - labels: - app.kubernetes.io/instance: flux-system - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v0.19.1 - control-plane: controller - name: webhook-receiver - namespace: flux-system -spec: - ports: - - name: http - port: 80 - protocol: TCP - targetPort: http-webhook - selector: - app: notification-controller - type: ClusterIP ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app.kubernetes.io/instance: flux-system - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v0.19.1 - control-plane: controller - name: helm-controller - namespace: flux-system -spec: - replicas: 1 - selector: - matchLabels: - app: helm-controller - template: - metadata: - annotations: - prometheus.io/port: "8080" - prometheus.io/scrape: "true" - labels: - app: helm-controller - spec: - containers: - - args: - - --events-addr=http://notification-controller/ - - --watch-all-namespaces=true - - --log-level=info - - --log-encoding=json - - --enable-leader-election - env: - - name: RUNTIME_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - image: ghcr.io/fluxcd/helm-controller:v0.12.1 - imagePullPolicy: IfNotPresent - livenessProbe: - httpGet: - path: /healthz - port: healthz - name: manager - ports: - - containerPort: 8080 - name: http-prom - - containerPort: 9440 - name: healthz - protocol: TCP - readinessProbe: - httpGet: - path: /readyz - port: healthz - resources: - limits: - cpu: 1000m - memory: 1Gi - requests: - cpu: 100m - memory: 64Mi - securityContext: - allowPrivilegeEscalation: false - readOnlyRootFilesystem: true - volumeMounts: - - mountPath: /tmp - name: temp - nodeSelector: - kubernetes.io/os: linux - serviceAccountName: helm-controller - terminationGracePeriodSeconds: 600 - volumes: - - emptyDir: {} - name: temp ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app.kubernetes.io/instance: flux-system - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v0.19.1 - control-plane: controller - name: kustomize-controller - namespace: flux-system -spec: - replicas: 1 - selector: - matchLabels: - app: kustomize-controller - template: - metadata: - annotations: - prometheus.io/port: "8080" - prometheus.io/scrape: "true" - labels: - app: kustomize-controller - spec: - containers: - - args: - - --events-addr=http://notification-controller/ - - --watch-all-namespaces=true - - --log-level=info - - --log-encoding=json - - --enable-leader-election - env: - - name: RUNTIME_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - image: ghcr.io/fluxcd/kustomize-controller:v0.16.0 - imagePullPolicy: IfNotPresent - livenessProbe: - httpGet: - path: /healthz - port: healthz - name: manager - ports: - - containerPort: 8080 - name: http-prom - - containerPort: 9440 - name: healthz - protocol: TCP - readinessProbe: - httpGet: - path: /readyz - port: healthz - resources: - limits: - cpu: 1000m - memory: 1Gi - requests: - cpu: 100m - memory: 64Mi - securityContext: - allowPrivilegeEscalation: false - readOnlyRootFilesystem: true - volumeMounts: - - mountPath: /tmp - name: temp - nodeSelector: - kubernetes.io/os: linux - securityContext: - fsGroup: 1337 - serviceAccountName: kustomize-controller - terminationGracePeriodSeconds: 60 - volumes: - - emptyDir: {} - name: temp ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app.kubernetes.io/instance: flux-system - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v0.19.1 - control-plane: controller - name: notification-controller - namespace: flux-system -spec: - replicas: 1 - selector: - matchLabels: - app: notification-controller - template: - metadata: - annotations: - prometheus.io/port: "8080" - prometheus.io/scrape: "true" - labels: - app: notification-controller - spec: - containers: - - args: - - --watch-all-namespaces=true - - --log-level=info - - --log-encoding=json - - --enable-leader-election - env: - - name: RUNTIME_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - image: ghcr.io/fluxcd/notification-controller:v0.18.1 - imagePullPolicy: IfNotPresent - livenessProbe: - httpGet: - path: /healthz - port: healthz - name: manager - ports: - - containerPort: 9090 - name: http - - containerPort: 9292 - name: http-webhook - - containerPort: 8080 - name: http-prom - - containerPort: 9440 - name: healthz - protocol: TCP - readinessProbe: - httpGet: - path: /readyz - port: healthz - resources: - limits: - cpu: 1000m - memory: 1Gi - requests: - cpu: 100m - memory: 64Mi - securityContext: - allowPrivilegeEscalation: false - readOnlyRootFilesystem: true - volumeMounts: - - mountPath: /tmp - name: temp - nodeSelector: - kubernetes.io/os: linux - serviceAccountName: notification-controller - terminationGracePeriodSeconds: 10 - volumes: - - emptyDir: {} - name: temp ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app.kubernetes.io/instance: flux-system - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v0.19.1 - control-plane: controller - name: source-controller - namespace: flux-system -spec: - replicas: 1 - selector: - matchLabels: - app: source-controller - strategy: - type: Recreate - template: - metadata: - annotations: - prometheus.io/port: "8080" - prometheus.io/scrape: "true" - labels: - app: source-controller - spec: - containers: - - args: - - --events-addr=http://notification-controller/ - - --watch-all-namespaces=true - - --log-level=info - - --log-encoding=json - - --enable-leader-election - - --storage-path=/data - - --storage-adv-addr=source-controller.$(RUNTIME_NAMESPACE).svc.cluster.local. - env: - - name: RUNTIME_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - image: ghcr.io/fluxcd/source-controller:v0.16.1 - imagePullPolicy: IfNotPresent - livenessProbe: - httpGet: - path: /healthz - port: healthz - name: manager - ports: - - containerPort: 9090 - name: http - - containerPort: 8080 - name: http-prom - - containerPort: 9440 - name: healthz - readinessProbe: - httpGet: - path: / - port: http - resources: - limits: - cpu: 1000m - memory: 1Gi - requests: - cpu: 50m - memory: 64Mi - securityContext: - allowPrivilegeEscalation: false - readOnlyRootFilesystem: true - volumeMounts: - - mountPath: /data - name: data - - mountPath: /tmp - name: tmp - nodeSelector: - kubernetes.io/os: linux - securityContext: - fsGroup: 1337 - serviceAccountName: source-controller - terminationGracePeriodSeconds: 10 - volumes: - - emptyDir: {} - name: data - - emptyDir: {} - name: tmp ---- -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - labels: - app.kubernetes.io/instance: flux-system - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v0.19.1 - name: allow-egress - namespace: flux-system -spec: - egress: - - {} - ingress: - - from: - - podSelector: {} - podSelector: {} - policyTypes: - - Ingress - - Egress ---- -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - labels: - app.kubernetes.io/instance: flux-system - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v0.19.1 - name: allow-scraping - namespace: flux-system -spec: - ingress: - - from: - - namespaceSelector: {} - ports: - - port: 8080 - protocol: TCP - podSelector: {} - policyTypes: - - Ingress ---- -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - labels: - app.kubernetes.io/instance: flux-system - app.kubernetes.io/part-of: flux - app.kubernetes.io/version: v0.19.1 - name: allow-webhooks - namespace: flux-system -spec: - ingress: - - from: - - namespaceSelector: {} - podSelector: - matchLabels: - app: notification-controller - policyTypes: - - Ingress diff --git a/flake.lock b/flake.lock new file mode 100644 index 00000000..225e39e1 --- /dev/null +++ b/flake.lock @@ -0,0 +1,1741 @@ +{ + "nodes": { + "alejandra": { + "inputs": { + "fenix": "fenix_2", + "flakeCompat": "flakeCompat", + "nixpkgs": [ + "webcord", + "dream2nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1658427149, + "narHash": "sha256-ToD/1z/q5VHsLMrS2h96vjJoLho59eNRtknOUd19ey8=", + "owner": "kamadorueda", + "repo": "alejandra", + "rev": "f5a22afd2adfb249b4e68e0b33aa1f0fb73fb1be", + "type": "github" + }, + "original": { + "owner": "kamadorueda", + "repo": "alejandra", + "type": "github" + } + }, + "all-cabal-json": { + "flake": false, + "locked": { + "lastModified": 1665552503, + "narHash": "sha256-r14RmRSwzv5c+bWKUDaze6pXM7nOsiz1H8nvFHJvufc=", + "owner": "nix-community", + "repo": "all-cabal-json", + "rev": "d7c0434eebffb305071404edcf9d5cd99703878e", + "type": "github" + }, + "original": { + "owner": "nix-community", + "ref": "hackage", + "repo": "all-cabal-json", + "type": "github" + } + }, + "attic": { + "inputs": { + "crane": "crane", + "flake-compat": "flake-compat", + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs", + "nixpkgs-stable": "nixpkgs-stable" + }, + "locked": { + "lastModified": 1698258239, + "narHash": "sha256-qnhoYYIJ0L/P7H/f56lQUEvpzNlXh4sxuHpRERV+B44=", + "owner": "zhaofengli", + "repo": "attic", + "rev": "e9918bc6be268da6fa97af6ced15193d8a0421c0", + "type": "github" + }, + "original": { + "owner": "zhaofengli", + "repo": "attic", + "type": "github" + } + }, + "beautysh": { + "inputs": { + "nixpkgs": [ + "nixvim", + "nixpkgs" + ], + "poetry2nix": "poetry2nix", + "utils": "utils_3" + }, + "locked": { + "lastModified": 1680308980, + "narHash": "sha256-aUEHV0jk2qIFP3jlsWYWhBbm+w/N9gzH3e4I5DcdB5s=", + "owner": "lovesegfault", + "repo": "beautysh", + "rev": "9845efc3ea3e86cc0d41465d720a47f521b2799c", + "type": "github" + }, + "original": { + "owner": "lovesegfault", + "repo": "beautysh", + "type": "github" + } + }, + "blobs": { + "flake": false, + "locked": { + "lastModified": 1604995301, + "narHash": "sha256-wcLzgLec6SGJA8fx1OEN1yV/Py5b+U5iyYpksUY/yLw=", + "owner": "simple-nixos-mailserver", + "repo": "blobs", + "rev": "2cccdf1ca48316f2cfd1c9a0017e8de5a7156265", + "type": "gitlab" + }, + "original": { + "owner": "simple-nixos-mailserver", + "repo": "blobs", + "type": "gitlab" + } + }, + "colmena": { + "inputs": { + "flake-compat": "flake-compat_2", + "flake-utils": "flake-utils_2", + "nixpkgs": "nixpkgs_2", + "stable": "stable" + }, + "locked": { + "lastModified": 1699171528, + "narHash": "sha256-ZsN6y+tgN5w84oAqRQpMhIvQM39ZNSZoZvn2AK0QYr4=", + "owner": "zhaofengli", + "repo": "colmena", + "rev": "665603956a1c3040d756987bc7a810ffe86a3b15", + "type": "github" + }, + "original": { + "owner": "zhaofengli", + "repo": "colmena", + "type": "github" + } + }, + "comma": { + "inputs": { + "flake-compat": "flake-compat_3", + "naersk": "naersk", + "nixpkgs": "nixpkgs_3", + "utils": "utils" + }, + "locked": { + "lastModified": 1698440846, + "narHash": "sha256-GKvNrjbuuHoahfGK9V2UMtT6qf91SWLdXrrTITBmR6k=", + "owner": "nix-community", + "repo": "comma", + "rev": "5ecd5024b4e490a0a69628c5ae96506f141551c0", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "comma", + "type": "github" + } + }, + "crane": { + "inputs": { + "flake-compat": [ + "attic", + "flake-compat" + ], + "flake-utils": [ + "attic", + "flake-utils" + ], + "nixpkgs": [ + "attic", + "nixpkgs" + ], + "rust-overlay": "rust-overlay" + }, + "locked": { + "lastModified": 1677892403, + "narHash": "sha256-/Wi0L1spSWLFj+UQxN3j0mPYMoc7ZoAujpUF/juFVII=", + "owner": "ipetkov", + "repo": "crane", + "rev": "105e27adb70a9890986b6d543a67761cbc1964a2", + "type": "github" + }, + "original": { + "owner": "ipetkov", + "repo": "crane", + "type": "github" + } + }, + "crane_2": { + "inputs": { + "nixpkgs": [ + "lanzaboote", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1699218802, + "narHash": "sha256-5l0W4Q7z7A4BCstaF5JuBqXOVrZ3Vqst5+hUnP7EdUc=", + "owner": "ipetkov", + "repo": "crane", + "rev": "2d6c2aaff5a05e443eb15efddc21f9c73720340c", + "type": "github" + }, + "original": { + "owner": "ipetkov", + "repo": "crane", + "type": "github" + } + }, + "crane_3": { + "flake": false, + "locked": { + "lastModified": 1670284777, + "narHash": "sha256-JF0pc0s4z/X+Iy+lNHOwUQ8I5bz+q7uX4HrKTNIEj24=", + "owner": "ipetkov", + "repo": "crane", + "rev": "2243fb9c872de25cb564a02d324ea6a5b9853052", + "type": "github" + }, + "original": { + "owner": "ipetkov", + "repo": "crane", + "type": "github" + } + }, + "devshell": { + "flake": false, + "locked": { + "lastModified": 1663445644, + "narHash": "sha256-+xVlcK60x7VY1vRJbNUEAHi17ZuoQxAIH4S4iUFUGBA=", + "owner": "numtide", + "repo": "devshell", + "rev": "e3dc3e21594fe07bdb24bdf1c8657acaa4cb8f66", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "devshell", + "type": "github" + } + }, + "dream2nix": { + "inputs": { + "alejandra": "alejandra", + "all-cabal-json": "all-cabal-json", + "crane": "crane_3", + "devshell": "devshell", + "flake-parts": "flake-parts_2", + "flake-utils-pre-commit": "flake-utils-pre-commit", + "ghc-utils": "ghc-utils", + "gomod2nix": "gomod2nix", + "mach-nix": "mach-nix", + "nix-pypi-fetcher": "nix-pypi-fetcher", + "nixpkgs": [ + "webcord", + "nixpkgs" + ], + "poetry2nix": "poetry2nix_2", + "pre-commit-hooks": "pre-commit-hooks_2" + }, + "locked": { + "lastModified": 1670715183, + "narHash": "sha256-l3OhVCCimrN1HFPfqfKAyzuMuPxNXZYLsI9w7AaQXv8=", + "owner": "nix-community", + "repo": "dream2nix", + "rev": "3d6f13ef9d4cb8c41bc83383bbec3e74865ef90d", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "dream2nix", + "type": "github" + } + }, + "fenix": { + "inputs": { + "nixpkgs": [ + "riff", + "nixpkgs" + ], + "rust-analyzer-src": "rust-analyzer-src" + }, + "locked": { + "lastModified": 1686896497, + "narHash": "sha256-IphIS1KpiFXp/j0v7mEMhtw51uvU5F0mqF2j4//7VAA=", + "owner": "nix-community", + "repo": "fenix", + "rev": "9c69d11badcd78710d7d8665bc3d2e1adc450ffe", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "fenix", + "type": "github" + } + }, + "fenix_2": { + "inputs": { + "nixpkgs": [ + "webcord", + "dream2nix", + "alejandra", + "nixpkgs" + ], + "rust-analyzer-src": "rust-analyzer-src_2" + }, + "locked": { + "lastModified": 1657607339, + "narHash": "sha256-HaqoAwlbVVZH2n4P3jN2FFPMpVuhxDy1poNOR7kzODc=", + "owner": "nix-community", + "repo": "fenix", + "rev": "b814c83d9e6aa5a28d0cf356ecfdafb2505ad37d", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "fenix", + "type": "github" + } + }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1673956053, + "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_2": { + "flake": false, + "locked": { + "lastModified": 1650374568, + "narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "b4a34015c698c7793d592d66adbab377907a2be8", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_3": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_4": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_5": { + "flake": false, + "locked": { + "lastModified": 1668681692, + "narHash": "sha256-Ht91NGdewz8IQLtWZ9LCeNXMSXHUss+9COoqu6JLmXU=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "009399224d5e398d03b22badca40a37ac85412a1", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_6": { + "flake": false, + "locked": { + "lastModified": 1673956053, + "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_7": { + "flake": false, + "locked": { + "lastModified": 1673956053, + "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-parts": { + "inputs": { + "nixpkgs-lib": [ + "lanzaboote", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1698882062, + "narHash": "sha256-HkhafUayIqxXyHH1X8d9RDl1M2CkFgZLjKD3MzabiEo=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "8c9fa2545007b49a5db5f650ae91f227672c3877", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-parts_2": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib" + }, + "locked": { + "lastModified": 1668450977, + "narHash": "sha256-cfLhMhnvXn6x1vPm+Jow3RiFAUSCw/l1utktCw5rVA4=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "d591857e9d7dd9ddbfba0ea02b43b927c3c0f1fa", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-utils": { + "locked": { + "lastModified": 1667395993, + "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils-pre-commit": { + "locked": { + "lastModified": 1644229661, + "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { + "locked": { + "lastModified": 1659877975, + "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_3": { + "inputs": { + "systems": "systems_2" + }, + "locked": { + "lastModified": 1694529238, + "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_4": { + "inputs": { + "systems": "systems_3" + }, + "locked": { + "lastModified": 1694529238, + "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_5": { + "inputs": { + "systems": "systems_4" + }, + "locked": { + "lastModified": 1685518550, + "narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_6": { + "locked": { + "lastModified": 1678901627, + "narHash": "sha256-U02riOqrKKzwjsxc/400XnElV+UtPUQWpANPlyazjH0=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "93a2b84fc4b70d9e089d029deacc3583435c2ed6", + "type": "github" + }, + "original": { + "id": "flake-utils", + "type": "indirect" + } + }, + "flake-utils_7": { + "inputs": { + "systems": "systems_6" + }, + "locked": { + "lastModified": 1681202837, + "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "cfacdce06f30d2b68473a46042957675eebb3401", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flakeCompat": { + "flake": false, + "locked": { + "lastModified": 1650374568, + "narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "b4a34015c698c7793d592d66adbab377907a2be8", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "ghc-utils": { + "flake": false, + "locked": { + "lastModified": 1662774800, + "narHash": "sha256-1Rd2eohGUw/s1tfvkepeYpg8kCEXiIot0RijapUjAkE=", + "ref": "refs/heads/master", + "rev": "bb3a2d3dc52ff0253fb9c2812bd7aa2da03e0fea", + "revCount": 1072, + "type": "git", + "url": "https://gitlab.haskell.org/bgamari/ghc-utils" + }, + "original": { + "type": "git", + "url": "https://gitlab.haskell.org/bgamari/ghc-utils" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "lanzaboote", + "pre-commit-hooks-nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1660459072, + "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "gitignore_2": { + "inputs": { + "nixpkgs": [ + "nixvim", + "pre-commit-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1660459072, + "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "gomod2nix": { + "flake": false, + "locked": { + "lastModified": 1627572165, + "narHash": "sha256-MFpwnkvQpauj799b4QTBJQFEddbD02+Ln5k92QyHOSk=", + "owner": "tweag", + "repo": "gomod2nix", + "rev": "67f22dd738d092c6ba88e420350ada0ed4992ae8", + "type": "github" + }, + "original": { + "owner": "tweag", + "repo": "gomod2nix", + "type": "github" + } + }, + "home-manager": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1701071203, + "narHash": "sha256-lQywA7QU/vzTdZ1apI0PfgCWNyQobXUYghVrR5zuIeM=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "db1878f013b52ba5e4034db7c1b63e8d04173a86", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "home-manager", + "type": "github" + } + }, + "lanzaboote": { + "inputs": { + "crane": "crane_2", + "flake-compat": "flake-compat_4", + "flake-parts": "flake-parts", + "flake-utils": "flake-utils_3", + "nixpkgs": [ + "nixpkgs" + ], + "pre-commit-hooks-nix": "pre-commit-hooks-nix", + "rust-overlay": "rust-overlay_2" + }, + "locked": { + "lastModified": 1700811440, + "narHash": "sha256-wrJpW3JCJ9egZpYUMne4c3PFEp+vmkTj5VFpPAT4xdY=", + "owner": "nix-community", + "repo": "lanzaboote", + "rev": "cbafc8f8fe388fba6f2c27224276f5f984f9ae47", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "lanzaboote", + "type": "github" + } + }, + "lowdown-src": { + "flake": false, + "locked": { + "lastModified": 1633514407, + "narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=", + "owner": "kristapsdz", + "repo": "lowdown", + "rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8", + "type": "github" + }, + "original": { + "owner": "kristapsdz", + "repo": "lowdown", + "type": "github" + } + }, + "mach-nix": { + "flake": false, + "locked": { + "lastModified": 1634711045, + "narHash": "sha256-m5A2Ty88NChLyFhXucECj6+AuiMZPHXNbw+9Kcs7F6Y=", + "owner": "DavHau", + "repo": "mach-nix", + "rev": "4433f74a97b94b596fa6cd9b9c0402104aceef5d", + "type": "github" + }, + "original": { + "id": "mach-nix", + "type": "indirect" + } + }, + "mailserver": { + "inputs": { + "blobs": "blobs", + "flake-compat": "flake-compat_5", + "nixpkgs": [ + "nixpkgs" + ], + "nixpkgs-22_11": "nixpkgs-22_11", + "nixpkgs-23_05": "nixpkgs-23_05", + "utils": "utils_2" + }, + "locked": { + "lastModified": 1700085753, + "narHash": "sha256-qtib7f3eRwfaUF+VziJXiBcZFqpHCAXS4HlrFsnzzl4=", + "owner": "simple-nixos-mailserver", + "repo": "nixos-mailserver", + "rev": "008d78cc21959e33d0d31f375b88353a7d7121ae", + "type": "gitlab" + }, + "original": { + "owner": "simple-nixos-mailserver", + "repo": "nixos-mailserver", + "type": "gitlab" + } + }, + "naersk": { + "inputs": { + "nixpkgs": [ + "comma", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1697664192, + "narHash": "sha256-nRTG3rYEGFV2+putRiC96+kNXDyKaPJgT6K/1FWN7yo=", + "owner": "nix-community", + "repo": "naersk", + "rev": "636a9b5dd7f2ad7d7c3af929ecf95e4d4fab9e97", + "type": "github" + }, + "original": { + "owner": "nix-community", + "ref": "master", + "repo": "naersk", + "type": "github" + } + }, + "naersk_2": { + "inputs": { + "nixpkgs": [ + "riff", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1686572087, + "narHash": "sha256-jXTut7ZSYqLEgm/nTk7TuVL2ExahTip605bLINklAnQ=", + "owner": "nix-community", + "repo": "naersk", + "rev": "8507af04eb40c5520bd35d9ce6f9d2342cea5ad1", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "naersk", + "type": "github" + } + }, + "nix": { + "inputs": { + "lowdown-src": "lowdown-src", + "nixpkgs": "nixpkgs_7", + "nixpkgs-regression": "nixpkgs-regression" + }, + "locked": { + "lastModified": 1654239108, + "narHash": "sha256-0JzuElxLe5DxM+R4tvBYfvQnMGCERZy4KMRf0JYxxS4=", + "owner": "nixos", + "repo": "nix", + "rev": "1dd7253133c4dfd2e7a16ad6fe505442cef38a5b", + "type": "github" + }, + "original": { + "id": "nix", + "type": "indirect" + } + }, + "nix-pypi-fetcher": { + "flake": false, + "locked": { + "lastModified": 1669065297, + "narHash": "sha256-UStjXjNIuIm7SzMOWvuYWIHBkPUKQ8Id63BMJjnIDoA=", + "owner": "DavHau", + "repo": "nix-pypi-fetcher", + "rev": "a9885ac6a091576b5195d547ac743d45a2a615ac", + "type": "github" + }, + "original": { + "owner": "DavHau", + "repo": "nix-pypi-fetcher", + "type": "github" + } + }, + "nixlib": { + "locked": { + "lastModified": 1693701915, + "narHash": "sha256-waHPLdDYUOHSEtMKKabcKIMhlUOHPOOPQ9UyFeEoovs=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "f5af57d3ef9947a70ac86e42695231ac1ad00c25", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" + } + }, + "nixos-generators": { + "inputs": { + "nixlib": "nixlib", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1696058303, + "narHash": "sha256-eNqKWpF5zG0SrgbbtljFOrRgFgRzCc4++TMFADBMLnc=", + "owner": "nix-community", + "repo": "nixos-generators", + "rev": "150f38bd1e09e20987feacb1b0d5991357532fb5", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixos-generators", + "type": "github" + } + }, + "nixos-hardware": { + "locked": { + "lastModified": 1701020860, + "narHash": "sha256-NwnRn04C8s+hH+KdVtGmVB1FFNIG7DtPJmQSCBDaET4=", + "owner": "nixos", + "repo": "nixos-hardware", + "rev": "b006ec52fce23b1d57f6ab4a42d7400732e9a0a2", + "type": "github" + }, + "original": { + "owner": "nixos", + "repo": "nixos-hardware", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1691853136, + "narHash": "sha256-wTzDsRV4HN8A2Sl0SVQY0q8ILs90CD43Ha//7gNZE+E=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "f0451844bbdf545f696f029d1448de4906c7f753", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-22_11": { + "locked": { + "lastModified": 1669558522, + "narHash": "sha256-yqxn+wOiPqe6cxzOo4leeJOp1bXE/fjPEi/3F/bBHv8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "ce5fe99df1f15a09a91a86be9738d68fadfbad82", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-22.11", + "type": "indirect" + } + }, + "nixpkgs-23_05": { + "locked": { + "lastModified": 1684782344, + "narHash": "sha256-SHN8hPYYSX0thDrMLMWPWYulK3YFgASOrCsIL3AJ78g=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "8966c43feba2c701ed624302b6a935f97bcbdf88", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-23.05", + "type": "indirect" + } + }, + "nixpkgs-lib": { + "locked": { + "dir": "lib", + "lastModified": 1665349835, + "narHash": "sha256-UK4urM3iN80UXQ7EaOappDzcisYIuEURFRoGQ/yPkug=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "34c5293a71ffdb2fe054eb5288adc1882c1eb0b1", + "type": "github" + }, + "original": { + "dir": "lib", + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-regression": { + "locked": { + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + } + }, + "nixpkgs-stable": { + "locked": { + "lastModified": 1685004253, + "narHash": "sha256-AbVL1nN/TDicUQ5wXZ8xdLERxz/eJr7+o8lqkIOVuaE=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "3e01645c40b92d29f3ae76344a6d654986a91a91", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-23.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-stable_2": { + "locked": { + "lastModified": 1685801374, + "narHash": "sha256-otaSUoFEMM+LjBI1XL/xGB5ao6IwnZOXc47qhIgJe8U=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "c37ca420157f4abc31e26f436c1145f8951ff373", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-23.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-stable_3": { + "locked": { + "lastModified": 1685801374, + "narHash": "sha256-otaSUoFEMM+LjBI1XL/xGB5ao6IwnZOXc47qhIgJe8U=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "c37ca420157f4abc31e26f436c1145f8951ff373", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-23.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_10": { + "locked": { + "lastModified": 1670507980, + "narHash": "sha256-riNZa0xzM1it3pzxciwALeMs+0CsBMWIW2FqulzK8vM=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "2787fc7d1e51404678614bf0fe92fc296746eec0", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1696019113, + "narHash": "sha256-X3+DKYWJm93DRSdC5M6K5hLqzSya9BjibtBsuARoPco=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "f5892ddac112a1e9b3612c39af1b72987ee5783a", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { + "locked": { + "lastModified": 1697915759, + "narHash": "sha256-WyMj5jGcecD+KC8gEs+wFth1J1wjisZf8kVZH13f1Zo=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "51d906d2341c9e866e48c2efcaac0f2d70bfd43e", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_4": { + "locked": { + "lastModified": 1701038920, + "narHash": "sha256-qlEfi8fhKK2oJwX4V6BPEo0qbpWQzQYRU4LrDya/zi0=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "28f167a2e998faa5a42896add2a43ff5685832a0", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-unstable-small", + "type": "indirect" + } + }, + "nixpkgs_5": { + "locked": { + "lastModified": 1700612854, + "narHash": "sha256-yrQ8osMD+vDLGFX7pcwsY/Qr5PUd6OmDMYJZzZi0+zc=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "19cbff58383a4ae384dea4d1d0c823d72b49d614", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_6": { + "locked": { + "lastModified": 1686736559, + "narHash": "sha256-YyUSVoOKIDAscTx7IZhF9x3qgZ9dPNF19fKk+4c5irc=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "ddf4688dc7aeb14e8a3c549cb6aa6337f187a884", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-23.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_7": { + "locked": { + "lastModified": 1645296114, + "narHash": "sha256-y53N7TyIkXsjMpOG7RhvqJFGDacLs9HlyHeSTBioqYU=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "530a53dcbc9437363471167a5e4762c5fcfa34a1", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-21.05-small", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_8": { + "locked": { + "lastModified": 1696165369, + "narHash": "sha256-pd1cjFHCoEf9q5f9B0HhlOwwpBI9RP3HbUE6xjI7wAI=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "d7186d62bb68fac3c90f1d95515e613ef299e992", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_9": { + "locked": { + "lastModified": 1682526928, + "narHash": "sha256-2cKh4O6t1rQ8Ok+v16URynmb0rV7oZPEbXkU0owNLQs=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "d6b863fd9b7bb962e6f9fdf292419a775e772891", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_stable": { + "locked": { + "lastModified": 1700989516, + "narHash": "sha256-oKbmPa2wpTHh9XB3+zIx97uMZGNnp97GPliKKG2/plo=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "d2e4de209881b38392933fabf303cde3454b0b4c", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-23.05", + "type": "indirect" + } + }, + "nixvim": { + "inputs": { + "beautysh": "beautysh", + "flake-utils": "flake-utils_4", + "nixpkgs": "nixpkgs_5", + "pre-commit-hooks": "pre-commit-hooks" + }, + "locked": { + "lastModified": 1700831612, + "narHash": "sha256-4rjt03g847UpPYshwItJqFqxHJ6l4aoXqDVT9CNOCu4=", + "owner": "pta2002", + "repo": "nixvim", + "rev": "bacdae2c508defccdff1af8511e4d639d26d3d47", + "type": "github" + }, + "original": { + "owner": "pta2002", + "repo": "nixvim", + "type": "github" + } + }, + "nur": { + "locked": { + "lastModified": 1701078355, + "narHash": "sha256-BIi0h4DwYk9sjm6JxCncZAYRNnuN+W2dggVM+rMkUDQ=", + "owner": "nix-community", + "repo": "NUR", + "rev": "1300118335519d491e7a0bd2d45d07162c567380", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "NUR", + "type": "github" + } + }, + "poetry2nix": { + "inputs": { + "flake-utils": [ + "nixvim", + "beautysh", + "utils" + ], + "nixpkgs": [ + "nixvim", + "beautysh", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1658665240, + "narHash": "sha256-/wkx7D7enyBPRjIkK0w7QxLQhzEkb3UxNQnjyc3FTUI=", + "owner": "nix-community", + "repo": "poetry2nix", + "rev": "8b8edc85d24661d5a6d0d71d6a7011f3e699780f", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "poetry2nix", + "type": "github" + } + }, + "poetry2nix_2": { + "flake": false, + "locked": { + "lastModified": 1666918719, + "narHash": "sha256-BkK42fjAku+2WgCOv2/1NrPa754eQPV7gPBmoKQBWlc=", + "owner": "nix-community", + "repo": "poetry2nix", + "rev": "289efb187123656a116b915206e66852f038720e", + "type": "github" + }, + "original": { + "owner": "nix-community", + "ref": "1.36.0", + "repo": "poetry2nix", + "type": "github" + } + }, + "pre-commit-hooks": { + "inputs": { + "flake-compat": "flake-compat_6", + "flake-utils": "flake-utils_5", + "gitignore": "gitignore_2", + "nixpkgs": [ + "nixvim", + "nixpkgs" + ], + "nixpkgs-stable": "nixpkgs-stable_3" + }, + "locked": { + "lastModified": 1700064067, + "narHash": "sha256-1ZWNDzhu8UlVCK7+DUN9dVQfiHX1bv6OQP9VxstY/gs=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "e558068cba67b23b4fbc5537173dbb43748a17e8", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "pre-commit-hooks-nix": { + "inputs": { + "flake-compat": [ + "lanzaboote", + "flake-compat" + ], + "flake-utils": [ + "lanzaboote", + "flake-utils" + ], + "gitignore": "gitignore", + "nixpkgs": [ + "lanzaboote", + "nixpkgs" + ], + "nixpkgs-stable": "nixpkgs-stable_2" + }, + "locked": { + "lastModified": 1699271226, + "narHash": "sha256-8Jt1KW3xTjolD6c6OjJm9USx/jmL+VVmbooADCkdDfU=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "ea758da1a6dcde6dc36db348ed690d09b9864128", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "pre-commit-hooks_2": { + "inputs": { + "flake-utils": [ + "webcord", + "dream2nix", + "flake-utils-pre-commit" + ], + "nixpkgs": [ + "webcord", + "dream2nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1646153636, + "narHash": "sha256-AlWHMzK+xJ1mG267FdT8dCq/HvLCA6jwmx2ZUy5O8tY=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "b6bc0b21e1617e2b07d8205e7fae7224036dfa4b", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "riff": { + "inputs": { + "fenix": "fenix", + "naersk": "naersk_2", + "nixpkgs": "nixpkgs_6" + }, + "locked": { + "lastModified": 1690193312, + "narHash": "sha256-JZQoHRBpNM1ucZ9A9ZE3Q67z8AuaBa/WKIS2Wm8zHHo=", + "owner": "DeterminateSystems", + "repo": "riff", + "rev": "aec5418dbae0c468652eaac7f8f3d85ed83c89ce", + "type": "github" + }, + "original": { + "owner": "DeterminateSystems", + "repo": "riff", + "type": "github" + } + }, + "root": { + "inputs": { + "attic": "attic", + "colmena": "colmena", + "comma": "comma", + "home-manager": "home-manager", + "lanzaboote": "lanzaboote", + "mailserver": "mailserver", + "nixos-generators": "nixos-generators", + "nixos-hardware": "nixos-hardware", + "nixpkgs": "nixpkgs_4", + "nixpkgs_stable": "nixpkgs_stable", + "nixvim": "nixvim", + "nur": "nur", + "riff": "riff", + "vault-secrets": "vault-secrets", + "vault-unseal": "vault-unseal", + "webcord": "webcord" + } + }, + "rust-analyzer-src": { + "flake": false, + "locked": { + "lastModified": 1686818168, + "narHash": "sha256-yyoJmC17T6mXqthzgGiTKSdUJ0cTEuqQmkmd3iW4ay8=", + "owner": "rust-lang", + "repo": "rust-analyzer", + "rev": "ff864fbb9fc21f0cdae408fe8f5b2f43141b45a7", + "type": "github" + }, + "original": { + "owner": "rust-lang", + "ref": "nightly", + "repo": "rust-analyzer", + "type": "github" + } + }, + "rust-analyzer-src_2": { + "flake": false, + "locked": { + "lastModified": 1657557289, + "narHash": "sha256-PRW+nUwuqNTRAEa83SfX+7g+g8nQ+2MMbasQ9nt6+UM=", + "owner": "rust-lang", + "repo": "rust-analyzer", + "rev": "caf23f29144b371035b864a1017dbc32573ad56d", + "type": "github" + }, + "original": { + "owner": "rust-lang", + "ref": "nightly", + "repo": "rust-analyzer", + "type": "github" + } + }, + "rust-overlay": { + "inputs": { + "flake-utils": [ + "attic", + "crane", + "flake-utils" + ], + "nixpkgs": [ + "attic", + "crane", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1675391458, + "narHash": "sha256-ukDKZw922BnK5ohL9LhwtaDAdCsJL7L6ScNEyF1lO9w=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "383a4acfd11d778d5c2efcf28376cbd845eeaedf", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, + "rust-overlay_2": { + "inputs": { + "flake-utils": [ + "lanzaboote", + "flake-utils" + ], + "nixpkgs": [ + "lanzaboote", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1699409596, + "narHash": "sha256-L3g1smIol3dGTxkUQOlNShJtZLvjLzvtbaeTRizwZBU=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "58240e1ac627cef3ea30c7732fedfb4f51afd8e7", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, + "stable": { + "locked": { + "lastModified": 1696039360, + "narHash": "sha256-g7nIUV4uq1TOVeVIDEZLb005suTWCUjSY0zYOlSBsyE=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "32dcb45f66c0487e92db8303a798ebc548cadedc", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-23.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_3": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_4": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_5": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_6": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1694529238, + "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "utils_2": { + "locked": { + "lastModified": 1605370193, + "narHash": "sha256-YyMTf3URDL/otKdKgtoMChu4vfVL3vCMkRqpGifhUn0=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "5021eac20303a61fafe17224c087f5519baed54d", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "utils_3": { + "locked": { + "lastModified": 1678901627, + "narHash": "sha256-U02riOqrKKzwjsxc/400XnElV+UtPUQWpANPlyazjH0=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "93a2b84fc4b70d9e089d029deacc3583435c2ed6", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "utils_4": { + "inputs": { + "systems": "systems_5" + }, + "locked": { + "lastModified": 1694529238, + "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "vault-secrets": { + "inputs": { + "flake-compat": "flake-compat_7", + "flake-utils": "flake-utils_6", + "nix": "nix", + "nixpkgs": "nixpkgs_8", + "utils": "utils_4" + }, + "locked": { + "lastModified": 1699433213, + "narHash": "sha256-NbYXC4jjAuxbw1mL7w5LqYd3jBKnwxk36jTQA8rnERM=", + "owner": "serokell", + "repo": "vault-secrets", + "rev": "7686f5d6f0411040407435e4361663b7fabaf171", + "type": "github" + }, + "original": { + "owner": "serokell", + "repo": "vault-secrets", + "type": "github" + } + }, + "vault-unseal": { + "inputs": { + "flake-utils": "flake-utils_7", + "nixpkgs": "nixpkgs_9" + }, + "locked": { + "lastModified": 1683013874, + "narHash": "sha256-B8bQb9IMkrDvtqFUoF/PuBma8Qa2jU7Xv7cFSchg9V8=", + "ref": "refs/heads/main", + "rev": "91e7262e87878609c2d6619210988b241e8f8f62", + "revCount": 11, + "type": "git", + "url": "https://git.0x76.dev/v/vault-unseal.git" + }, + "original": { + "type": "git", + "url": "https://git.0x76.dev/v/vault-unseal.git" + } + }, + "webcord": { + "inputs": { + "dream2nix": "dream2nix", + "nixpkgs": "nixpkgs_10", + "webcord": "webcord_2" + }, + "locked": { + "lastModified": 1670874335, + "narHash": "sha256-nJ1LUVj3dIHP5B+XkZXUvY39OqaZn/MMHSFwsOSPnwI=", + "owner": "fufexan", + "repo": "webcord-flake", + "rev": "b462d57c36d664b48f047c96b2f9de091bff6e8b", + "type": "github" + }, + "original": { + "owner": "fufexan", + "repo": "webcord-flake", + "type": "github" + } + }, + "webcord_2": { + "flake": false, + "locked": { + "lastModified": 1670713990, + "narHash": "sha256-e+y/M+/gjezHoNrdXeFhqtvxbPdhRSDOQlwK1nUhNfo=", + "owner": "SpacingBat3", + "repo": "WebCord", + "rev": "80ba858c025e0bb59510f7136211948d8ae10ece", + "type": "github" + }, + "original": { + "owner": "SpacingBat3", + "repo": "WebCord", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 00000000..3ef1297e --- /dev/null +++ b/flake.nix @@ -0,0 +1,165 @@ +{ + description = "0x76's infrastructure"; + + # For minecraft use: + # * https://github.com/Infinidoge/nix-minecraft + + inputs = { + nixpkgs.url = "nixpkgs/nixos-unstable-small"; + + nixpkgs_stable.url = "nixpkgs/nixos-23.05"; + + nur.url = "github:nix-community/NUR"; + + colmena.url = "github:zhaofengli/colmena"; + + vault-secrets.url = "github:serokell/vault-secrets"; + + home-manager.url = "github:nix-community/home-manager"; + home-manager.inputs.nixpkgs.follows = "nixpkgs"; + + riff.url = "github:DeterminateSystems/riff"; + + webcord.url = "github:fufexan/webcord-flake"; + + comma.url = "github:nix-community/comma"; + + mailserver.url = "gitlab:simple-nixos-mailserver/nixos-mailserver"; + mailserver.inputs.nixpkgs.follows = "nixpkgs"; + + nixvim.url = "github:pta2002/nixvim"; + + nixos-generators.url = "github:nix-community/nixos-generators"; + nixos-generators.inputs.nixpkgs.follows = "nixpkgs"; + + nixos-hardware.url = "github:nixos/nixos-hardware"; + + lanzaboote = { + url = "github:nix-community/lanzaboote"; + + # Optional but recommended to limit the size of your system closure. + inputs.nixpkgs.follows = "nixpkgs"; + }; + + vault-unseal.url = "git+https://git.0x76.dev/v/vault-unseal.git"; + + attic.url = "github:zhaofengli/attic"; + }; + + outputs = + { self + , nixpkgs + , nixpkgs_stable + , vault-secrets + , colmena + , nixos-generators + , nur + , attic + , ... + }@inputs: + let + inherit (nixpkgs) lib; + + util = import ./nixos/util.nix inputs; + inherit (util) hosts flat_hosts nixHosts; + + system = "x86_64-linux"; + + pkgs = import nixpkgs { + inherit system; + config.allowUnfree = true; + overlays = [ (import ./nixos/pkgs) vault-secrets.overlay nur.overlay ]; + }; + + pkgs_stable = import nixpkgs_stable { + inherit system; + config.allowUnfree = true; + }; + + # Define args each module gets access to (access to hosts is useful for DNS/DHCP) + specialArgs = { inherit hosts flat_hosts inputs pkgs_stable; }; + + # Script to apply local colmena deployments + apply-local = pkgs.writeShellScriptBin "apply-local" '' + "${ + colmena.packages.${system}.colmena + }"/bin/colmena apply-local --sudo $@ + ''; + + fast-repl = pkgs.writeShellScriptBin "fast-repl" '' + source /etc/set-environment + nix repl --file "${./.}/repl.nix" $@ + ''; + in + { + # Make the nixosConfigurations for compat reasons (e.g. vault) + nixosConfigurations = + (import (inputs.colmena + "/src/nix/hive/eval.nix") { + rawFlake = self; + colmenaOptions = + import (inputs.colmena + "/src/nix/hive/options.nix"); + colmenaModules = + import (inputs.colmena + "/src/nix/hive/modules.nix"); + }).nodes; + + # Make the colmena configuration + colmena = lib.foldr (el: acc: acc // util.mkColmenaHost el) + { + meta = { + inherit specialArgs; + nixpkgs = pkgs; + }; + } + nixHosts; + + packages.${system} = { + inherit apply-local; + + default = colmena.packages.${system}.colmena; + + proxmox-lxc = nixos-generators.nixosGenerate { + inherit system specialArgs; + format = "proxmox-lxc"; + modules = util.base_imports + ++ [ (import ./nixos/templates/proxmox-lxc.nix) ]; + }; + + # Broken + # proxmox-vm = nixos-generators.nixosGenerate { + # inherit system pkgs specialArgs; + # format = "proxmox"; + # modules = util.base_imports + # ++ [ (import ./nixos/templates/proxmox-vm.nix) ]; + # }; + }; + + # Use by running `nix develop` + devShells.${system}.default = pkgs.mkShell { + VAULT_ADDR = "http://vault.olympus:8200/"; + buildInputs = with pkgs; [ + attic.packages.${pkgs.system}.attic + apply-local + colmena.packages.${system}.colmena + cachix + deadnix + fluxcd + k9s + kubectl + kubectx + statix + terraform + nixfmt + nixpkgs-fmt + nixUnstable + nil + vault + yamllint + jq + (vault-push-approle-envs self { }) + (vault-push-approles self { }) + fast-repl + weave-gitops + ]; + }; + }; +} diff --git a/flux/.gitignore b/flux/.gitignore new file mode 100644 index 00000000..ec8d5548 --- /dev/null +++ b/flux/.gitignore @@ -0,0 +1 @@ +old_cluster diff --git a/flux/README.md b/flux/README.md new file mode 100644 index 00000000..252502d8 --- /dev/null +++ b/flux/README.md @@ -0,0 +1,12 @@ +# Kubernetes Cluster +This is my personal Kubernetes Cluster. [Flux] watches this git repo and reconciles and changes made to the cluster. + +## Bootstrap +```sh +flux bootstrap git --url ssh://gitea@git.0x76.dev:42/v/infrastructure.git --branch=main --path=flux/olympus/base --ssh-key-algorithm=ed25519 +``` + +## References +Heavily inspired by: [onedr0p's cluster](https://github.com/onedr0p/home-cluster) + +[Flux]: https://github.com/fluxcd/flux2 diff --git a/flux/olympus/apps/flux-system/external-secret.yaml b/flux/olympus/apps/flux-system/external-secret.yaml new file mode 100644 index 00000000..c12fbe01 --- /dev/null +++ b/flux/olympus/apps/flux-system/external-secret.yaml @@ -0,0 +1,15 @@ +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: weave-gitops + namespace: flux-system +spec: + refreshInterval: "5m" + secretStoreRef: + name: vault + kind: ClusterSecretStore + target: + name: oidc-auth + dataFrom: + - extract: + key: flux-system/weave-gitops diff --git a/flux/olympus/apps/flux-system/kustomization.yaml b/flux/olympus/apps/flux-system/kustomization.yaml new file mode 100644 index 00000000..29912dbe --- /dev/null +++ b/flux/olympus/apps/flux-system/kustomization.yaml @@ -0,0 +1,6 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - rbac.yaml + - external-secret.yaml + - weave-gitops-dashboard.yaml diff --git a/flux/olympus/apps/flux-system/rbac.yaml b/flux/olympus/apps/flux-system/rbac.yaml new file mode 100644 index 00000000..a3a7d0ca --- /dev/null +++ b/flux/olympus/apps/flux-system/rbac.yaml @@ -0,0 +1,76 @@ +--- +# Admin cluster role +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: weave-admin +rules: + # Flux Resources + - apiGroups: ["kustomize.toolkit.fluxcd.io"] + resources: ["kustomizations"] + verbs: ["get", "list", "patch"] + - apiGroups: ["helm.toolkit.fluxcd.io"] + resources: ["helmreleases"] + verbs: ["get", "list", "patch"] + - apiGroups: ["source.toolkit.fluxcd.io"] + resources: + [ + "buckets", + "helmcharts", + "gitrepositories", + "helmrepositories", + "ocirepositories", + ] + verbs: ["get", "list", "patch"] + - apiGroups: ["notification.toolkit.fluxcd.io"] + resources: ["providers", "alerts"] + verbs: ["get", "list"] + - apiGroups: ["infra.contrib.fluxcd.io"] + resources: ["terraforms"] + verbs: ["get", "list", "patch"] + # Resources managed via Flux + - apiGroups: [""] + resources: + [ + "configmaps", + "secrets", + "pods", + "services", + "namespaces", + "persistentvolumes", + "persistentvolumeclaims", + ] + verbs: ["get", "list"] + - apiGroups: ["apps"] + resources: ["deployments", "replicasets", "statefulsets"] + verbs: ["get", "list"] + - apiGroups: ["batch"] + resources: ["jobs", "cronjobs"] + verbs: ["get", "list"] + - apiGroups: ["autoscaling"] + resources: ["horizontalpodautoscalers"] + verbs: ["get", "list"] + - apiGroups: ["rbac.authorization.k8s.io"] + resources: ["roles", "clusterroles", "rolebindings", "clusterrolebindings"] + verbs: ["get", "list"] + - apiGroups: ["networking.k8s.io"] + resources: ["ingresses"] + verbs: ["get", "list"] + # Feedback + - apiGroups: [""] + resources: ["events"] + verbs: ["get", "watch", "list"] +--- +# Bind the cluster admin role to admins +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: weave-admin +subjects: + - kind: User + name: "victor@xirion.net" + apiGroup: rbac.authorization.k8s.io +roleRef: + kind: ClusterRole + name: weave-admin + apiGroup: rbac.authorization.k8s.io diff --git a/flux/olympus/apps/flux-system/weave-gitops-dashboard.yaml b/flux/olympus/apps/flux-system/weave-gitops-dashboard.yaml new file mode 100644 index 00000000..9a70ed7d --- /dev/null +++ b/flux/olympus/apps/flux-system/weave-gitops-dashboard.yaml @@ -0,0 +1,48 @@ +--- +apiVersion: source.toolkit.fluxcd.io/v1 +kind: HelmRepository +metadata: + annotations: + metadata.weave.works/description: This is the source location for the Weave GitOps + Dashboard's helm chart. + labels: + app.kubernetes.io/component: ui + app.kubernetes.io/created-by: weave-gitops-cli + app.kubernetes.io/name: weave-gitops-dashboard + app.kubernetes.io/part-of: weave-gitops + name: ww-gitops + namespace: flux-system +spec: + interval: 1h0m0s + type: oci + url: oci://ghcr.io/weaveworks/charts +--- +apiVersion: helm.toolkit.fluxcd.io/v2beta1 +kind: HelmRelease +metadata: + annotations: + metadata.weave.works/description: This is the Weave GitOps Dashboard. It provides + a simple way to get insights into your GitOps workloads. + name: ww-gitops + namespace: flux-system +spec: + chart: + spec: + chart: weave-gitops + sourceRef: + kind: HelmRepository + name: ww-gitops + interval: 1h0m0s + values: + ingress: + enabled: true + hosts: + - host: flux.0x76.dev + paths: + - path: / + pathType: ImplementationSpecific + adminUser: + create: true + passwordHash: $2a$10$uIY/YYe.CcRerpVvfk04muX86hLfXRH.K6jATZaVPqp.bnUIu/bsC + username: admin + diff --git a/flux/olympus/apps/kustomization.yaml b/flux/olympus/apps/kustomization.yaml new file mode 100644 index 00000000..396b9e10 --- /dev/null +++ b/flux/olympus/apps/kustomization.yaml @@ -0,0 +1,6 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - flux-system + - services + - websites diff --git a/cluster/flux-system/kustomization.yaml b/flux/olympus/apps/services/kustomization.yaml similarity index 65% rename from cluster/flux-system/kustomization.yaml rename to flux/olympus/apps/services/kustomization.yaml index 3842229e..4ddab702 100644 --- a/cluster/flux-system/kustomization.yaml +++ b/flux/olympus/apps/services/kustomization.yaml @@ -1,5 +1,4 @@ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: -- gotk-components.yaml -- gotk-sync.yaml + - renovate diff --git a/flux/olympus/apps/services/renovate/config.yaml b/flux/olympus/apps/services/renovate/config.yaml new file mode 100644 index 00000000..53683839 --- /dev/null +++ b/flux/olympus/apps/services/renovate/config.yaml @@ -0,0 +1,57 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: renovate + namespace: services +data: + config.js: |- + module.exports = { + "binarySource": "install", + "repositories": ["v/infrastructure"], + "flux": { + "fileMatch": ["flux/.+\\.ya?ml$"] + }, + "helm-values": { + "fileMatch": ["flux/.+\\.ya?ml$"] + }, + "kubernetes": { + "fileMatch": ["flux/.+\\.ya?ml$"] + }, + "hostRules": [ + { + "hostType": "docker", + "matchHost": "ghcr.io", + "username": "NULLx76", + "password": process.env.GITHUB_COM_TOKEN + } + ], + "packageRules": [ + { + "automerge": true, + "automergeType": "branch", + "matchUpdateTypes": ["minor", "patch", "pin", "digest"], + "matchPackageNames": [ + "renovate/renovate" + ], + "matchPackagePrefixes": [ + "git.0x76.dev" + ] + } + ], + // ignore individual fluxcd images + "ignoreDeps": [ + "ghcr.io/fluxcd/helm-controller", + "ghcr.io/fluxcd/image-automation-controller", + "ghcr.io/fluxcd/image-reflector-controller", + "ghcr.io/fluxcd/kustomize-controller", + "ghcr.io/fluxcd/notification-controller", + "ghcr.io/fluxcd/source-controller" + ], + "regexManagers": [ + { + "fileMatch": [".+\\.nix"], + "matchStrings": ["image\\s*=\\s*\"(?.*?):(?.*?)\"\\s*;\\s*"], + "datasourceTemplate": "docker" + } + ] + }; diff --git a/flux/olympus/apps/services/renovate/cronjob.yaml b/flux/olympus/apps/services/renovate/cronjob.yaml new file mode 100644 index 00000000..c7f652c9 --- /dev/null +++ b/flux/olympus/apps/services/renovate/cronjob.yaml @@ -0,0 +1,46 @@ +apiVersion: batch/v1 +kind: CronJob +metadata: + name: renovate + namespace: services +spec: + # Run every 8 hours + schedule: "0 */8 * * *" + concurrencyPolicy: Forbid + jobTemplate: + spec: + template: + spec: + volumes: + - name: config-volume + configMap: + name: renovate + - name: work-volume + emptyDir: {} + containers: + - name: renovate + image: renovate/renovate:37.68.4 + volumeMounts: + - name: config-volume + mountPath: /opt/renovate/ + - name: work-volume + mountPath: /tmp/renovate/ + env: + - name: LOG_LEVEL + value: debug + - name: RENOVATE_ENDPOINT + value: "https://git.0x76.dev/api/v1/" + - name: RENOVATE_PLATFORM + value: gitea + - name: RENOVATE_AUTODISCOVER + value: "false" + - name: RENOVATE_GIT_AUTHOR + value: "Renovate Bot " + - name: RENOVATE_CONFIG_FILE + value: "/opt/renovate/config.js" + - name: RENOVATE_BASE_DIR + value: "/tmp/renovate" + envFrom: + - secretRef: + name: renovate + restartPolicy: Never diff --git a/flux/olympus/apps/services/renovate/external-secret.yaml b/flux/olympus/apps/services/renovate/external-secret.yaml new file mode 100644 index 00000000..40637451 --- /dev/null +++ b/flux/olympus/apps/services/renovate/external-secret.yaml @@ -0,0 +1,21 @@ +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: renovate + namespace: services +spec: + refreshInterval: "5m" + secretStoreRef: + name: vault + kind: ClusterSecretStore + target: + name: renovate + data: + - secretKey: RENOVATE_TOKEN + remoteRef: + key: gitops/renovate + property: gitea_token + - secretKey: GITHUB_COM_TOKEN + remoteRef: + key: gitops/renovate + property: github_token diff --git a/flux/olympus/apps/services/renovate/kustomization.yaml b/flux/olympus/apps/services/renovate/kustomization.yaml new file mode 100644 index 00000000..74e8575d --- /dev/null +++ b/flux/olympus/apps/services/renovate/kustomization.yaml @@ -0,0 +1,6 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - external-secret.yaml + - config.yaml + - cronjob.yaml diff --git a/flux/olympus/apps/websites/0x76.yaml b/flux/olympus/apps/websites/0x76.yaml new file mode 100644 index 00000000..7b768e6c --- /dev/null +++ b/flux/olympus/apps/websites/0x76.yaml @@ -0,0 +1,52 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: x76dev + namespace: websites + labels: + app: x76dev +spec: + replicas: 1 + selector: + matchLabels: + app: x76dev + template: + metadata: + labels: + app: x76dev + spec: + containers: + - name: x76dev + image: git.0x76.dev/v/0x76.dev:5 + ports: + - containerPort: 80 +--- +apiVersion: v1 +kind: Service +metadata: + name: x76dev + namespace: websites +spec: + selector: + app: x76dev + ports: + - protocol: TCP + port: 80 +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: x76dev + namespace: websites +spec: + rules: + - host: "0x76.dev" + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: x76dev + port: + number: 80 diff --git a/flux/olympus/apps/websites/blog.yaml b/flux/olympus/apps/websites/blog.yaml new file mode 100644 index 00000000..52e763e5 --- /dev/null +++ b/flux/olympus/apps/websites/blog.yaml @@ -0,0 +1,52 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: blog + namespace: websites + labels: + app: blog +spec: + replicas: 1 + selector: + matchLabels: + app: blog + template: + metadata: + labels: + app: blog + spec: + containers: + - name: blog + image: git.0x76.dev/v/blog.xirion.net:5 + ports: + - containerPort: 8080 +--- +apiVersion: v1 +kind: Service +metadata: + name: blog + namespace: websites +spec: + selector: + app: blog + ports: + - protocol: TCP + port: 8080 +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: blog + namespace: websites +spec: + rules: + - host: "blog.xirion.net" + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: blog + port: + number: 8080 diff --git a/flux/olympus/apps/websites/internal.yaml b/flux/olympus/apps/websites/internal.yaml new file mode 100644 index 00000000..50d2f244 --- /dev/null +++ b/flux/olympus/apps/websites/internal.yaml @@ -0,0 +1,52 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: internal + namespace: websites + labels: + app: internal +spec: + replicas: 1 + selector: + matchLabels: + app: internal + template: + metadata: + labels: + app: internal + spec: + containers: + - name: internal + image: git.0x76.dev/v/internal.xirion.net:1 + ports: + - containerPort: 8080 +--- +apiVersion: v1 +kind: Service +metadata: + name: internal + namespace: websites +spec: + selector: + app: internal + ports: + - protocol: TCP + port: 8080 +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: internal + namespace: websites +spec: + rules: + - host: "internal.xirion.net" + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: internal + port: + number: 8080 diff --git a/flux/olympus/apps/websites/kustomization.yaml b/flux/olympus/apps/websites/kustomization.yaml new file mode 100644 index 00000000..d3df4526 --- /dev/null +++ b/flux/olympus/apps/websites/kustomization.yaml @@ -0,0 +1,9 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +metadata: + namespace: websites +resources: + - 0x76.yaml + - internal.yaml + - blog.yaml + - xirion.yaml diff --git a/flux/olympus/apps/websites/xirion.yaml b/flux/olympus/apps/websites/xirion.yaml new file mode 100644 index 00000000..e7e311f1 --- /dev/null +++ b/flux/olympus/apps/websites/xirion.yaml @@ -0,0 +1,52 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: xirion + namespace: websites + labels: + app: xirion +spec: + replicas: 1 + selector: + matchLabels: + app: xirion + template: + metadata: + labels: + app: xirion + spec: + containers: + - name: xirion + image: git.0x76.dev/v/xirion.net:2 + ports: + - containerPort: 80 +--- +apiVersion: v1 +kind: Service +metadata: + name: xirion + namespace: websites +spec: + selector: + app: xirion + ports: + - protocol: TCP + port: 80 +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: xirion + namespace: websites +spec: + rules: + - host: "xirion.net" + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: xirion + port: + number: 80 diff --git a/flux/olympus/base/apps.yaml b/flux/olympus/base/apps.yaml new file mode 100644 index 00000000..0059a2e9 --- /dev/null +++ b/flux/olympus/base/apps.yaml @@ -0,0 +1,15 @@ +--- +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: apps + namespace: flux-system +spec: + interval: 10m0s + dependsOn: + - name: core + path: ./flux/olympus/apps + prune: true + sourceRef: + kind: GitRepository + name: flux-system diff --git a/flux/olympus/base/core.yaml b/flux/olympus/base/core.yaml new file mode 100644 index 00000000..f61c58c8 --- /dev/null +++ b/flux/olympus/base/core.yaml @@ -0,0 +1,13 @@ +--- +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: core + namespace: flux-system +spec: + interval: 10m0s + path: ./flux/olympus/core + prune: true + sourceRef: + kind: GitRepository + name: flux-system diff --git a/flux/olympus/base/flux-system/gotk-components.yaml b/flux/olympus/base/flux-system/gotk-components.yaml new file mode 100644 index 00000000..d8d8bed8 --- /dev/null +++ b/flux/olympus/base/flux-system/gotk-components.yaml @@ -0,0 +1,8029 @@ +--- +# This manifest was generated by flux. DO NOT EDIT. +# Flux Version: v2.1.2 +# Components: source-controller,kustomize-controller,helm-controller,notification-controller +apiVersion: v1 +kind: Namespace +metadata: + labels: + app.kubernetes.io/instance: flux-system + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: v2.1.2 + pod-security.kubernetes.io/warn: restricted + pod-security.kubernetes.io/warn-version: latest + name: flux-system +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + labels: + app.kubernetes.io/instance: flux-system + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: v2.1.2 + name: allow-egress + namespace: flux-system +spec: + egress: + - {} + ingress: + - from: + - podSelector: {} + podSelector: {} + policyTypes: + - Ingress + - Egress +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + labels: + app.kubernetes.io/instance: flux-system + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: v2.1.2 + name: allow-scraping + namespace: flux-system +spec: + ingress: + - from: + - namespaceSelector: {} + ports: + - port: 8080 + protocol: TCP + podSelector: {} + policyTypes: + - Ingress +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + labels: + app.kubernetes.io/instance: flux-system + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: v2.1.2 + name: allow-webhooks + namespace: flux-system +spec: + ingress: + - from: + - namespaceSelector: {} + podSelector: + matchLabels: + app: notification-controller + policyTypes: + - Ingress +--- +apiVersion: v1 +kind: ResourceQuota +metadata: + labels: + app.kubernetes.io/instance: flux-system + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: v2.1.2 + name: critical-pods-flux-system + namespace: flux-system +spec: + hard: + pods: "1000" + scopeSelector: + matchExpressions: + - operator: In + scopeName: PriorityClass + values: + - system-node-critical + - system-cluster-critical +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/instance: flux-system + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: v2.1.2 + name: crd-controller-flux-system +rules: +- apiGroups: + - source.toolkit.fluxcd.io + resources: + - '*' + verbs: + - '*' +- apiGroups: + - kustomize.toolkit.fluxcd.io + resources: + - '*' + verbs: + - '*' +- apiGroups: + - helm.toolkit.fluxcd.io + resources: + - '*' + verbs: + - '*' +- apiGroups: + - notification.toolkit.fluxcd.io + resources: + - '*' + verbs: + - '*' +- apiGroups: + - image.toolkit.fluxcd.io + resources: + - '*' + verbs: + - '*' +- apiGroups: + - "" + resources: + - namespaces + - secrets + - configmaps + - serviceaccounts + verbs: + - get + - list + - watch +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - configmaps/status + verbs: + - get + - update + - patch +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/instance: flux-system + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: v2.1.2 + rbac.authorization.k8s.io/aggregate-to-admin: "true" + rbac.authorization.k8s.io/aggregate-to-edit: "true" + name: flux-edit-flux-system +rules: +- apiGroups: + - notification.toolkit.fluxcd.io + - source.toolkit.fluxcd.io + - helm.toolkit.fluxcd.io + - image.toolkit.fluxcd.io + - kustomize.toolkit.fluxcd.io + resources: + - '*' + verbs: + - create + - delete + - deletecollection + - patch + - update +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/instance: flux-system + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: v2.1.2 + rbac.authorization.k8s.io/aggregate-to-admin: "true" + rbac.authorization.k8s.io/aggregate-to-edit: "true" + rbac.authorization.k8s.io/aggregate-to-view: "true" + name: flux-view-flux-system +rules: +- apiGroups: + - notification.toolkit.fluxcd.io + - source.toolkit.fluxcd.io + - helm.toolkit.fluxcd.io + - image.toolkit.fluxcd.io + - kustomize.toolkit.fluxcd.io + resources: + - '*' + verbs: + - get + - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + app.kubernetes.io/instance: flux-system + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: v2.1.2 + name: cluster-reconciler-flux-system +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cluster-admin +subjects: +- kind: ServiceAccount + name: kustomize-controller + namespace: flux-system +- kind: ServiceAccount + name: helm-controller + namespace: flux-system +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + app.kubernetes.io/instance: flux-system + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: v2.1.2 + name: crd-controller-flux-system +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: crd-controller-flux-system +subjects: +- kind: ServiceAccount + name: kustomize-controller + namespace: flux-system +- kind: ServiceAccount + name: helm-controller + namespace: flux-system +- kind: ServiceAccount + name: source-controller + namespace: flux-system +- kind: ServiceAccount + name: notification-controller + namespace: flux-system +- kind: ServiceAccount + name: image-reflector-controller + namespace: flux-system +- kind: ServiceAccount + name: image-automation-controller + namespace: flux-system +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.0 + labels: + app.kubernetes.io/component: source-controller + app.kubernetes.io/instance: flux-system + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: v2.1.2 + name: buckets.source.toolkit.fluxcd.io +spec: + group: source.toolkit.fluxcd.io + names: + kind: Bucket + listKind: BucketList + plural: buckets + singular: bucket + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.endpoint + name: Endpoint + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + description: Bucket is the Schema for the buckets API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: BucketSpec defines the desired state of an S3 compatible + bucket + properties: + accessFrom: + description: AccessFrom defines an Access Control List for allowing + cross-namespace references to this object. + properties: + namespaceSelectors: + description: NamespaceSelectors is the list of namespace selectors + to which this ACL applies. Items in this list are evaluated + using a logical OR operation. + items: + description: NamespaceSelector selects the namespaces to which + this ACL applies. An empty map of MatchLabels matches all + namespaces in a cluster. + properties: + matchLabels: + additionalProperties: + type: string + description: MatchLabels is a map of {key,value} pairs. + A single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field is + "key", the operator is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + type: array + required: + - namespaceSelectors + type: object + bucketName: + description: The bucket name. + type: string + endpoint: + description: The bucket endpoint address. + type: string + ignore: + description: Ignore overrides the set of excluded patterns in the + .sourceignore format (which is the same as .gitignore). If not provided, + a default will be used, consult the documentation for your version + to find out what those are. + type: string + insecure: + description: Insecure allows connecting to a non-TLS S3 HTTP endpoint. + type: boolean + interval: + description: The interval at which to check for bucket updates. + type: string + provider: + default: generic + description: The S3 compatible storage provider name, default ('generic'). + enum: + - generic + - aws + - gcp + type: string + region: + description: The bucket region. + type: string + secretRef: + description: The name of the secret containing authentication credentials + for the Bucket. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + suspend: + description: This flag tells the controller to suspend the reconciliation + of this source. + type: boolean + timeout: + default: 60s + description: The timeout for download operations, defaults to 60s. + type: string + required: + - bucketName + - endpoint + - interval + type: object + status: + default: + observedGeneration: -1 + description: BucketStatus defines the observed state of a bucket + properties: + artifact: + description: Artifact represents the output of the last successful + Bucket sync. + properties: + checksum: + description: Checksum is the SHA256 checksum of the artifact. + type: string + lastUpdateTime: + description: LastUpdateTime is the timestamp corresponding to + the last update of this artifact. + format: date-time + type: string + path: + description: Path is the relative file path of this artifact. + type: string + revision: + description: Revision is a human readable identifier traceable + in the origin source system. It can be a Git commit SHA, Git + tag, a Helm index timestamp, a Helm chart version, etc. + type: string + url: + description: URL is the HTTP address of this artifact. + type: string + required: + - path + - url + type: object + conditions: + description: Conditions holds the conditions for the Bucket. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + lastHandledReconcileAt: + description: LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value can + be detected. + type: string + observedGeneration: + description: ObservedGeneration is the last observed generation. + format: int64 + type: integer + url: + description: URL is the download link for the artifact output of the + last Bucket sync. + type: string + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .spec.endpoint + name: Endpoint + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + name: v1beta2 + schema: + openAPIV3Schema: + description: Bucket is the Schema for the buckets API. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: BucketSpec specifies the required configuration to produce + an Artifact for an object storage bucket. + properties: + accessFrom: + description: 'AccessFrom specifies an Access Control List for allowing + cross-namespace references to this object. NOTE: Not implemented, + provisional as of https://github.com/fluxcd/flux2/pull/2092' + properties: + namespaceSelectors: + description: NamespaceSelectors is the list of namespace selectors + to which this ACL applies. Items in this list are evaluated + using a logical OR operation. + items: + description: NamespaceSelector selects the namespaces to which + this ACL applies. An empty map of MatchLabels matches all + namespaces in a cluster. + properties: + matchLabels: + additionalProperties: + type: string + description: MatchLabels is a map of {key,value} pairs. + A single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field is + "key", the operator is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + type: array + required: + - namespaceSelectors + type: object + bucketName: + description: BucketName is the name of the object storage bucket. + type: string + endpoint: + description: Endpoint is the object storage address the BucketName + is located at. + type: string + ignore: + description: Ignore overrides the set of excluded patterns in the + .sourceignore format (which is the same as .gitignore). If not provided, + a default will be used, consult the documentation for your version + to find out what those are. + type: string + insecure: + description: Insecure allows connecting to a non-TLS HTTP Endpoint. + type: boolean + interval: + description: Interval at which the Bucket Endpoint is checked for + updates. This interval is approximate and may be subject to jitter + to ensure efficient use of resources. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + provider: + default: generic + description: Provider of the object storage bucket. Defaults to 'generic', + which expects an S3 (API) compatible object storage. + enum: + - generic + - aws + - gcp + - azure + type: string + region: + description: Region of the Endpoint where the BucketName is located + in. + type: string + secretRef: + description: SecretRef specifies the Secret containing authentication + credentials for the Bucket. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + suspend: + description: Suspend tells the controller to suspend the reconciliation + of this Bucket. + type: boolean + timeout: + default: 60s + description: Timeout for fetch operations, defaults to 60s. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$ + type: string + required: + - bucketName + - endpoint + - interval + type: object + status: + default: + observedGeneration: -1 + description: BucketStatus records the observed state of a Bucket. + properties: + artifact: + description: Artifact represents the last successful Bucket reconciliation. + properties: + digest: + description: Digest is the digest of the file in the form of ':'. + pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ + type: string + lastUpdateTime: + description: LastUpdateTime is the timestamp corresponding to + the last update of the Artifact. + format: date-time + type: string + metadata: + additionalProperties: + type: string + description: Metadata holds upstream information such as OCI annotations. + type: object + path: + description: Path is the relative file path of the Artifact. It + can be used to locate the file in the root of the Artifact storage + on the local file system of the controller managing the Source. + type: string + revision: + description: Revision is a human-readable identifier traceable + in the origin source system. It can be a Git commit SHA, Git + tag, a Helm chart version, etc. + type: string + size: + description: Size is the number of bytes in the file. + format: int64 + type: integer + url: + description: URL is the HTTP address of the Artifact as exposed + by the controller managing the Source. It can be used to retrieve + the Artifact for consumption, e.g. by another controller applying + the Artifact contents. + type: string + required: + - lastUpdateTime + - path + - revision + - url + type: object + conditions: + description: Conditions holds the conditions for the Bucket. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + lastHandledReconcileAt: + description: LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value can + be detected. + type: string + observedGeneration: + description: ObservedGeneration is the last observed generation of + the Bucket object. + format: int64 + type: integer + observedIgnore: + description: ObservedIgnore is the observed exclusion patterns used + for constructing the source artifact. + type: string + url: + description: URL is the dynamic fetch link for the latest Artifact. + It is provided on a "best effort" basis, and using the precise BucketStatus.Artifact + data is recommended. + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.0 + labels: + app.kubernetes.io/component: source-controller + app.kubernetes.io/instance: flux-system + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: v2.1.2 + name: gitrepositories.source.toolkit.fluxcd.io +spec: + group: source.toolkit.fluxcd.io + names: + kind: GitRepository + listKind: GitRepositoryList + plural: gitrepositories + shortNames: + - gitrepo + singular: gitrepository + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.url + name: URL + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + name: v1 + schema: + openAPIV3Schema: + description: GitRepository is the Schema for the gitrepositories API. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: GitRepositorySpec specifies the required configuration to + produce an Artifact for a Git repository. + properties: + ignore: + description: Ignore overrides the set of excluded patterns in the + .sourceignore format (which is the same as .gitignore). If not provided, + a default will be used, consult the documentation for your version + to find out what those are. + type: string + include: + description: Include specifies a list of GitRepository resources which + Artifacts should be included in the Artifact produced for this GitRepository. + items: + description: GitRepositoryInclude specifies a local reference to + a GitRepository which Artifact (sub-)contents must be included, + and where they should be placed. + properties: + fromPath: + description: FromPath specifies the path to copy contents from, + defaults to the root of the Artifact. + type: string + repository: + description: GitRepositoryRef specifies the GitRepository which + Artifact contents must be included. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + toPath: + description: ToPath specifies the path to copy contents to, + defaults to the name of the GitRepositoryRef. + type: string + required: + - repository + type: object + type: array + interval: + description: Interval at which the GitRepository URL is checked for + updates. This interval is approximate and may be subject to jitter + to ensure efficient use of resources. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + proxySecretRef: + description: ProxySecretRef specifies the Secret containing the proxy + configuration to use while communicating with the Git server. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + recurseSubmodules: + description: RecurseSubmodules enables the initialization of all submodules + within the GitRepository as cloned from the URL, using their default + settings. + type: boolean + ref: + description: Reference specifies the Git reference to resolve and + monitor for changes, defaults to the 'master' branch. + properties: + branch: + description: Branch to check out, defaults to 'master' if no other + field is defined. + type: string + commit: + description: "Commit SHA to check out, takes precedence over all + reference fields. \n This can be combined with Branch to shallow + clone the branch, in which the commit is expected to exist." + type: string + name: + description: "Name of the reference to check out; takes precedence + over Branch, Tag and SemVer. \n It must be a valid Git reference: + https://git-scm.com/docs/git-check-ref-format#_description Examples: + \"refs/heads/main\", \"refs/tags/v0.1.0\", \"refs/pull/420/head\", + \"refs/merge-requests/1/head\"" + type: string + semver: + description: SemVer tag expression to check out, takes precedence + over Tag. + type: string + tag: + description: Tag to check out, takes precedence over Branch. + type: string + type: object + secretRef: + description: SecretRef specifies the Secret containing authentication + credentials for the GitRepository. For HTTPS repositories the Secret + must contain 'username' and 'password' fields for basic auth or + 'bearerToken' field for token auth. For SSH repositories the Secret + must contain 'identity' and 'known_hosts' fields. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + suspend: + description: Suspend tells the controller to suspend the reconciliation + of this GitRepository. + type: boolean + timeout: + default: 60s + description: Timeout for Git operations like cloning, defaults to + 60s. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$ + type: string + url: + description: URL specifies the Git repository URL, it can be an HTTP/S + or SSH address. + pattern: ^(http|https|ssh)://.*$ + type: string + verify: + description: Verification specifies the configuration to verify the + Git commit signature(s). + properties: + mode: + default: HEAD + description: "Mode specifies which Git object(s) should be verified. + \n The variants \"head\" and \"HEAD\" both imply the same thing, + i.e. verify the commit that the HEAD of the Git repository points + to. The variant \"head\" solely exists to ensure backwards compatibility." + enum: + - head + - HEAD + - Tag + - TagAndHEAD + type: string + secretRef: + description: SecretRef specifies the Secret containing the public + keys of trusted Git authors. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + required: + - secretRef + type: object + required: + - interval + - url + type: object + status: + default: + observedGeneration: -1 + description: GitRepositoryStatus records the observed state of a Git repository. + properties: + artifact: + description: Artifact represents the last successful GitRepository + reconciliation. + properties: + digest: + description: Digest is the digest of the file in the form of ':'. + pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ + type: string + lastUpdateTime: + description: LastUpdateTime is the timestamp corresponding to + the last update of the Artifact. + format: date-time + type: string + metadata: + additionalProperties: + type: string + description: Metadata holds upstream information such as OCI annotations. + type: object + path: + description: Path is the relative file path of the Artifact. It + can be used to locate the file in the root of the Artifact storage + on the local file system of the controller managing the Source. + type: string + revision: + description: Revision is a human-readable identifier traceable + in the origin source system. It can be a Git commit SHA, Git + tag, a Helm chart version, etc. + type: string + size: + description: Size is the number of bytes in the file. + format: int64 + type: integer + url: + description: URL is the HTTP address of the Artifact as exposed + by the controller managing the Source. It can be used to retrieve + the Artifact for consumption, e.g. by another controller applying + the Artifact contents. + type: string + required: + - lastUpdateTime + - path + - revision + - url + type: object + conditions: + description: Conditions holds the conditions for the GitRepository. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + includedArtifacts: + description: IncludedArtifacts contains a list of the last successfully + included Artifacts as instructed by GitRepositorySpec.Include. + items: + description: Artifact represents the output of a Source reconciliation. + properties: + digest: + description: Digest is the digest of the file in the form of + ':'. + pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ + type: string + lastUpdateTime: + description: LastUpdateTime is the timestamp corresponding to + the last update of the Artifact. + format: date-time + type: string + metadata: + additionalProperties: + type: string + description: Metadata holds upstream information such as OCI + annotations. + type: object + path: + description: Path is the relative file path of the Artifact. + It can be used to locate the file in the root of the Artifact + storage on the local file system of the controller managing + the Source. + type: string + revision: + description: Revision is a human-readable identifier traceable + in the origin source system. It can be a Git commit SHA, Git + tag, a Helm chart version, etc. + type: string + size: + description: Size is the number of bytes in the file. + format: int64 + type: integer + url: + description: URL is the HTTP address of the Artifact as exposed + by the controller managing the Source. It can be used to retrieve + the Artifact for consumption, e.g. by another controller applying + the Artifact contents. + type: string + required: + - lastUpdateTime + - path + - revision + - url + type: object + type: array + lastHandledReconcileAt: + description: LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value can + be detected. + type: string + observedGeneration: + description: ObservedGeneration is the last observed generation of + the GitRepository object. + format: int64 + type: integer + observedIgnore: + description: ObservedIgnore is the observed exclusion patterns used + for constructing the source artifact. + type: string + observedInclude: + description: ObservedInclude is the observed list of GitRepository + resources used to produce the current Artifact. + items: + description: GitRepositoryInclude specifies a local reference to + a GitRepository which Artifact (sub-)contents must be included, + and where they should be placed. + properties: + fromPath: + description: FromPath specifies the path to copy contents from, + defaults to the root of the Artifact. + type: string + repository: + description: GitRepositoryRef specifies the GitRepository which + Artifact contents must be included. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + toPath: + description: ToPath specifies the path to copy contents to, + defaults to the name of the GitRepositoryRef. + type: string + required: + - repository + type: object + type: array + observedRecurseSubmodules: + description: ObservedRecurseSubmodules is the observed resource submodules + configuration used to produce the current Artifact. + type: boolean + sourceVerificationMode: + description: SourceVerificationMode is the last used verification + mode indicating which Git object(s) have been verified. + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .spec.url + name: URL + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + deprecated: true + deprecationWarning: v1beta1 GitRepository is deprecated, upgrade to v1 + name: v1beta1 + schema: + openAPIV3Schema: + description: GitRepository is the Schema for the gitrepositories API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: GitRepositorySpec defines the desired state of a Git repository. + properties: + accessFrom: + description: AccessFrom defines an Access Control List for allowing + cross-namespace references to this object. + properties: + namespaceSelectors: + description: NamespaceSelectors is the list of namespace selectors + to which this ACL applies. Items in this list are evaluated + using a logical OR operation. + items: + description: NamespaceSelector selects the namespaces to which + this ACL applies. An empty map of MatchLabels matches all + namespaces in a cluster. + properties: + matchLabels: + additionalProperties: + type: string + description: MatchLabels is a map of {key,value} pairs. + A single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field is + "key", the operator is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + type: array + required: + - namespaceSelectors + type: object + gitImplementation: + default: go-git + description: Determines which git client library to use. Defaults + to go-git, valid values are ('go-git', 'libgit2'). + enum: + - go-git + - libgit2 + type: string + ignore: + description: Ignore overrides the set of excluded patterns in the + .sourceignore format (which is the same as .gitignore). If not provided, + a default will be used, consult the documentation for your version + to find out what those are. + type: string + include: + description: Extra git repositories to map into the repository + items: + description: GitRepositoryInclude defines a source with a from and + to path. + properties: + fromPath: + description: The path to copy contents from, defaults to the + root directory. + type: string + repository: + description: Reference to a GitRepository to include. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + toPath: + description: The path to copy contents to, defaults to the name + of the source ref. + type: string + required: + - repository + type: object + type: array + interval: + description: The interval at which to check for repository updates. + type: string + recurseSubmodules: + description: When enabled, after the clone is created, initializes + all submodules within, using their default settings. This option + is available only when using the 'go-git' GitImplementation. + type: boolean + ref: + description: The Git reference to checkout and monitor for changes, + defaults to master branch. + properties: + branch: + description: The Git branch to checkout, defaults to master. + type: string + commit: + description: The Git commit SHA to checkout, if specified Tag + filters will be ignored. + type: string + semver: + description: The Git tag semver expression, takes precedence over + Tag. + type: string + tag: + description: The Git tag to checkout, takes precedence over Branch. + type: string + type: object + secretRef: + description: The secret name containing the Git credentials. For HTTPS + repositories the secret must contain username and password fields. + For SSH repositories the secret must contain identity and known_hosts + fields. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + suspend: + description: This flag tells the controller to suspend the reconciliation + of this source. + type: boolean + timeout: + default: 60s + description: The timeout for remote Git operations like cloning, defaults + to 60s. + type: string + url: + description: The repository URL, can be a HTTP/S or SSH address. + pattern: ^(http|https|ssh)://.*$ + type: string + verify: + description: Verify OpenPGP signature for the Git commit HEAD points + to. + properties: + mode: + description: Mode describes what git object should be verified, + currently ('head'). + enum: + - head + type: string + secretRef: + description: The secret name containing the public keys of all + trusted Git authors. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + required: + - mode + type: object + required: + - interval + - url + type: object + status: + default: + observedGeneration: -1 + description: GitRepositoryStatus defines the observed state of a Git repository. + properties: + artifact: + description: Artifact represents the output of the last successful + repository sync. + properties: + checksum: + description: Checksum is the SHA256 checksum of the artifact. + type: string + lastUpdateTime: + description: LastUpdateTime is the timestamp corresponding to + the last update of this artifact. + format: date-time + type: string + path: + description: Path is the relative file path of this artifact. + type: string + revision: + description: Revision is a human readable identifier traceable + in the origin source system. It can be a Git commit SHA, Git + tag, a Helm index timestamp, a Helm chart version, etc. + type: string + url: + description: URL is the HTTP address of this artifact. + type: string + required: + - path + - url + type: object + conditions: + description: Conditions holds the conditions for the GitRepository. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + includedArtifacts: + description: IncludedArtifacts represents the included artifacts from + the last successful repository sync. + items: + description: Artifact represents the output of a source synchronisation. + properties: + checksum: + description: Checksum is the SHA256 checksum of the artifact. + type: string + lastUpdateTime: + description: LastUpdateTime is the timestamp corresponding to + the last update of this artifact. + format: date-time + type: string + path: + description: Path is the relative file path of this artifact. + type: string + revision: + description: Revision is a human readable identifier traceable + in the origin source system. It can be a Git commit SHA, Git + tag, a Helm index timestamp, a Helm chart version, etc. + type: string + url: + description: URL is the HTTP address of this artifact. + type: string + required: + - path + - url + type: object + type: array + lastHandledReconcileAt: + description: LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value can + be detected. + type: string + observedGeneration: + description: ObservedGeneration is the last observed generation. + format: int64 + type: integer + url: + description: URL is the download link for the artifact output of the + last repository sync. + type: string + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .spec.url + name: URL + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + deprecated: true + deprecationWarning: v1beta2 GitRepository is deprecated, upgrade to v1 + name: v1beta2 + schema: + openAPIV3Schema: + description: GitRepository is the Schema for the gitrepositories API. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: GitRepositorySpec specifies the required configuration to + produce an Artifact for a Git repository. + properties: + accessFrom: + description: 'AccessFrom specifies an Access Control List for allowing + cross-namespace references to this object. NOTE: Not implemented, + provisional as of https://github.com/fluxcd/flux2/pull/2092' + properties: + namespaceSelectors: + description: NamespaceSelectors is the list of namespace selectors + to which this ACL applies. Items in this list are evaluated + using a logical OR operation. + items: + description: NamespaceSelector selects the namespaces to which + this ACL applies. An empty map of MatchLabels matches all + namespaces in a cluster. + properties: + matchLabels: + additionalProperties: + type: string + description: MatchLabels is a map of {key,value} pairs. + A single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field is + "key", the operator is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + type: array + required: + - namespaceSelectors + type: object + gitImplementation: + default: go-git + description: 'GitImplementation specifies which Git client library + implementation to use. Defaults to ''go-git'', valid values are + (''go-git'', ''libgit2''). Deprecated: gitImplementation is deprecated + now that ''go-git'' is the only supported implementation.' + enum: + - go-git + - libgit2 + type: string + ignore: + description: Ignore overrides the set of excluded patterns in the + .sourceignore format (which is the same as .gitignore). If not provided, + a default will be used, consult the documentation for your version + to find out what those are. + type: string + include: + description: Include specifies a list of GitRepository resources which + Artifacts should be included in the Artifact produced for this GitRepository. + items: + description: GitRepositoryInclude specifies a local reference to + a GitRepository which Artifact (sub-)contents must be included, + and where they should be placed. + properties: + fromPath: + description: FromPath specifies the path to copy contents from, + defaults to the root of the Artifact. + type: string + repository: + description: GitRepositoryRef specifies the GitRepository which + Artifact contents must be included. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + toPath: + description: ToPath specifies the path to copy contents to, + defaults to the name of the GitRepositoryRef. + type: string + required: + - repository + type: object + type: array + interval: + description: Interval at which to check the GitRepository for updates. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + recurseSubmodules: + description: RecurseSubmodules enables the initialization of all submodules + within the GitRepository as cloned from the URL, using their default + settings. + type: boolean + ref: + description: Reference specifies the Git reference to resolve and + monitor for changes, defaults to the 'master' branch. + properties: + branch: + description: Branch to check out, defaults to 'master' if no other + field is defined. + type: string + commit: + description: "Commit SHA to check out, takes precedence over all + reference fields. \n This can be combined with Branch to shallow + clone the branch, in which the commit is expected to exist." + type: string + name: + description: "Name of the reference to check out; takes precedence + over Branch, Tag and SemVer. \n It must be a valid Git reference: + https://git-scm.com/docs/git-check-ref-format#_description Examples: + \"refs/heads/main\", \"refs/tags/v0.1.0\", \"refs/pull/420/head\", + \"refs/merge-requests/1/head\"" + type: string + semver: + description: SemVer tag expression to check out, takes precedence + over Tag. + type: string + tag: + description: Tag to check out, takes precedence over Branch. + type: string + type: object + secretRef: + description: SecretRef specifies the Secret containing authentication + credentials for the GitRepository. For HTTPS repositories the Secret + must contain 'username' and 'password' fields for basic auth or + 'bearerToken' field for token auth. For SSH repositories the Secret + must contain 'identity' and 'known_hosts' fields. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + suspend: + description: Suspend tells the controller to suspend the reconciliation + of this GitRepository. + type: boolean + timeout: + default: 60s + description: Timeout for Git operations like cloning, defaults to + 60s. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$ + type: string + url: + description: URL specifies the Git repository URL, it can be an HTTP/S + or SSH address. + pattern: ^(http|https|ssh)://.*$ + type: string + verify: + description: Verification specifies the configuration to verify the + Git commit signature(s). + properties: + mode: + description: Mode specifies what Git object should be verified, + currently ('head'). + enum: + - head + type: string + secretRef: + description: SecretRef specifies the Secret containing the public + keys of trusted Git authors. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + required: + - mode + - secretRef + type: object + required: + - interval + - url + type: object + status: + default: + observedGeneration: -1 + description: GitRepositoryStatus records the observed state of a Git repository. + properties: + artifact: + description: Artifact represents the last successful GitRepository + reconciliation. + properties: + digest: + description: Digest is the digest of the file in the form of ':'. + pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ + type: string + lastUpdateTime: + description: LastUpdateTime is the timestamp corresponding to + the last update of the Artifact. + format: date-time + type: string + metadata: + additionalProperties: + type: string + description: Metadata holds upstream information such as OCI annotations. + type: object + path: + description: Path is the relative file path of the Artifact. It + can be used to locate the file in the root of the Artifact storage + on the local file system of the controller managing the Source. + type: string + revision: + description: Revision is a human-readable identifier traceable + in the origin source system. It can be a Git commit SHA, Git + tag, a Helm chart version, etc. + type: string + size: + description: Size is the number of bytes in the file. + format: int64 + type: integer + url: + description: URL is the HTTP address of the Artifact as exposed + by the controller managing the Source. It can be used to retrieve + the Artifact for consumption, e.g. by another controller applying + the Artifact contents. + type: string + required: + - lastUpdateTime + - path + - revision + - url + type: object + conditions: + description: Conditions holds the conditions for the GitRepository. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + contentConfigChecksum: + description: "ContentConfigChecksum is a checksum of all the configurations + related to the content of the source artifact: - .spec.ignore - + .spec.recurseSubmodules - .spec.included and the checksum of the + included artifacts observed in .status.observedGeneration version + of the object. This can be used to determine if the content of the + included repository has changed. It has the format of `:`, + for example: `sha256:`. \n Deprecated: Replaced with explicit + fields for observed artifact content config in the status." + type: string + includedArtifacts: + description: IncludedArtifacts contains a list of the last successfully + included Artifacts as instructed by GitRepositorySpec.Include. + items: + description: Artifact represents the output of a Source reconciliation. + properties: + digest: + description: Digest is the digest of the file in the form of + ':'. + pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ + type: string + lastUpdateTime: + description: LastUpdateTime is the timestamp corresponding to + the last update of the Artifact. + format: date-time + type: string + metadata: + additionalProperties: + type: string + description: Metadata holds upstream information such as OCI + annotations. + type: object + path: + description: Path is the relative file path of the Artifact. + It can be used to locate the file in the root of the Artifact + storage on the local file system of the controller managing + the Source. + type: string + revision: + description: Revision is a human-readable identifier traceable + in the origin source system. It can be a Git commit SHA, Git + tag, a Helm chart version, etc. + type: string + size: + description: Size is the number of bytes in the file. + format: int64 + type: integer + url: + description: URL is the HTTP address of the Artifact as exposed + by the controller managing the Source. It can be used to retrieve + the Artifact for consumption, e.g. by another controller applying + the Artifact contents. + type: string + required: + - lastUpdateTime + - path + - revision + - url + type: object + type: array + lastHandledReconcileAt: + description: LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value can + be detected. + type: string + observedGeneration: + description: ObservedGeneration is the last observed generation of + the GitRepository object. + format: int64 + type: integer + observedIgnore: + description: ObservedIgnore is the observed exclusion patterns used + for constructing the source artifact. + type: string + observedInclude: + description: ObservedInclude is the observed list of GitRepository + resources used to to produce the current Artifact. + items: + description: GitRepositoryInclude specifies a local reference to + a GitRepository which Artifact (sub-)contents must be included, + and where they should be placed. + properties: + fromPath: + description: FromPath specifies the path to copy contents from, + defaults to the root of the Artifact. + type: string + repository: + description: GitRepositoryRef specifies the GitRepository which + Artifact contents must be included. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + toPath: + description: ToPath specifies the path to copy contents to, + defaults to the name of the GitRepositoryRef. + type: string + required: + - repository + type: object + type: array + observedRecurseSubmodules: + description: ObservedRecurseSubmodules is the observed resource submodules + configuration used to produce the current Artifact. + type: boolean + url: + description: URL is the dynamic fetch link for the latest Artifact. + It is provided on a "best effort" basis, and using the precise GitRepositoryStatus.Artifact + data is recommended. + type: string + type: object + type: object + served: true + storage: false + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.0 + labels: + app.kubernetes.io/component: source-controller + app.kubernetes.io/instance: flux-system + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: v2.1.2 + name: helmcharts.source.toolkit.fluxcd.io +spec: + group: source.toolkit.fluxcd.io + names: + kind: HelmChart + listKind: HelmChartList + plural: helmcharts + shortNames: + - hc + singular: helmchart + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.chart + name: Chart + type: string + - jsonPath: .spec.version + name: Version + type: string + - jsonPath: .spec.sourceRef.kind + name: Source Kind + type: string + - jsonPath: .spec.sourceRef.name + name: Source Name + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + description: HelmChart is the Schema for the helmcharts API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: HelmChartSpec defines the desired state of a Helm chart. + properties: + accessFrom: + description: AccessFrom defines an Access Control List for allowing + cross-namespace references to this object. + properties: + namespaceSelectors: + description: NamespaceSelectors is the list of namespace selectors + to which this ACL applies. Items in this list are evaluated + using a logical OR operation. + items: + description: NamespaceSelector selects the namespaces to which + this ACL applies. An empty map of MatchLabels matches all + namespaces in a cluster. + properties: + matchLabels: + additionalProperties: + type: string + description: MatchLabels is a map of {key,value} pairs. + A single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field is + "key", the operator is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + type: array + required: + - namespaceSelectors + type: object + chart: + description: The name or path the Helm chart is available at in the + SourceRef. + type: string + interval: + description: The interval at which to check the Source for updates. + type: string + reconcileStrategy: + default: ChartVersion + description: Determines what enables the creation of a new artifact. + Valid values are ('ChartVersion', 'Revision'). See the documentation + of the values for an explanation on their behavior. Defaults to + ChartVersion when omitted. + enum: + - ChartVersion + - Revision + type: string + sourceRef: + description: The reference to the Source the chart is available at. + properties: + apiVersion: + description: APIVersion of the referent. + type: string + kind: + description: Kind of the referent, valid values are ('HelmRepository', + 'GitRepository', 'Bucket'). + enum: + - HelmRepository + - GitRepository + - Bucket + type: string + name: + description: Name of the referent. + type: string + required: + - kind + - name + type: object + suspend: + description: This flag tells the controller to suspend the reconciliation + of this source. + type: boolean + valuesFile: + description: Alternative values file to use as the default chart values, + expected to be a relative path in the SourceRef. Deprecated in favor + of ValuesFiles, for backwards compatibility the file defined here + is merged before the ValuesFiles items. Ignored when omitted. + type: string + valuesFiles: + description: Alternative list of values files to use as the chart + values (values.yaml is not included by default), expected to be + a relative path in the SourceRef. Values files are merged in the + order of this list with the last file overriding the first. Ignored + when omitted. + items: + type: string + type: array + version: + default: '*' + description: The chart version semver expression, ignored for charts + from GitRepository and Bucket sources. Defaults to latest when omitted. + type: string + required: + - chart + - interval + - sourceRef + type: object + status: + default: + observedGeneration: -1 + description: HelmChartStatus defines the observed state of the HelmChart. + properties: + artifact: + description: Artifact represents the output of the last successful + chart sync. + properties: + checksum: + description: Checksum is the SHA256 checksum of the artifact. + type: string + lastUpdateTime: + description: LastUpdateTime is the timestamp corresponding to + the last update of this artifact. + format: date-time + type: string + path: + description: Path is the relative file path of this artifact. + type: string + revision: + description: Revision is a human readable identifier traceable + in the origin source system. It can be a Git commit SHA, Git + tag, a Helm index timestamp, a Helm chart version, etc. + type: string + url: + description: URL is the HTTP address of this artifact. + type: string + required: + - path + - url + type: object + conditions: + description: Conditions holds the conditions for the HelmChart. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + lastHandledReconcileAt: + description: LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value can + be detected. + type: string + observedGeneration: + description: ObservedGeneration is the last observed generation. + format: int64 + type: integer + url: + description: URL is the download link for the last chart pulled. + type: string + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .spec.chart + name: Chart + type: string + - jsonPath: .spec.version + name: Version + type: string + - jsonPath: .spec.sourceRef.kind + name: Source Kind + type: string + - jsonPath: .spec.sourceRef.name + name: Source Name + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + name: v1beta2 + schema: + openAPIV3Schema: + description: HelmChart is the Schema for the helmcharts API. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: HelmChartSpec specifies the desired state of a Helm chart. + properties: + accessFrom: + description: 'AccessFrom specifies an Access Control List for allowing + cross-namespace references to this object. NOTE: Not implemented, + provisional as of https://github.com/fluxcd/flux2/pull/2092' + properties: + namespaceSelectors: + description: NamespaceSelectors is the list of namespace selectors + to which this ACL applies. Items in this list are evaluated + using a logical OR operation. + items: + description: NamespaceSelector selects the namespaces to which + this ACL applies. An empty map of MatchLabels matches all + namespaces in a cluster. + properties: + matchLabels: + additionalProperties: + type: string + description: MatchLabels is a map of {key,value} pairs. + A single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field is + "key", the operator is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + type: array + required: + - namespaceSelectors + type: object + chart: + description: Chart is the name or path the Helm chart is available + at in the SourceRef. + type: string + interval: + description: Interval at which the HelmChart SourceRef is checked + for updates. This interval is approximate and may be subject to + jitter to ensure efficient use of resources. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + reconcileStrategy: + default: ChartVersion + description: ReconcileStrategy determines what enables the creation + of a new artifact. Valid values are ('ChartVersion', 'Revision'). + See the documentation of the values for an explanation on their + behavior. Defaults to ChartVersion when omitted. + enum: + - ChartVersion + - Revision + type: string + sourceRef: + description: SourceRef is the reference to the Source the chart is + available at. + properties: + apiVersion: + description: APIVersion of the referent. + type: string + kind: + description: Kind of the referent, valid values are ('HelmRepository', + 'GitRepository', 'Bucket'). + enum: + - HelmRepository + - GitRepository + - Bucket + type: string + name: + description: Name of the referent. + type: string + required: + - kind + - name + type: object + suspend: + description: Suspend tells the controller to suspend the reconciliation + of this source. + type: boolean + valuesFile: + description: ValuesFile is an alternative values file to use as the + default chart values, expected to be a relative path in the SourceRef. + Deprecated in favor of ValuesFiles, for backwards compatibility + the file specified here is merged before the ValuesFiles items. + Ignored when omitted. + type: string + valuesFiles: + description: ValuesFiles is an alternative list of values files to + use as the chart values (values.yaml is not included by default), + expected to be a relative path in the SourceRef. Values files are + merged in the order of this list with the last file overriding the + first. Ignored when omitted. + items: + type: string + type: array + verify: + description: Verify contains the secret name containing the trusted + public keys used to verify the signature and specifies which provider + to use to check whether OCI image is authentic. This field is only + supported when using HelmRepository source with spec.type 'oci'. + Chart dependencies, which are not bundled in the umbrella chart + artifact, are not verified. + properties: + provider: + default: cosign + description: Provider specifies the technology used to sign the + OCI Artifact. + enum: + - cosign + type: string + secretRef: + description: SecretRef specifies the Kubernetes Secret containing + the trusted public keys. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + required: + - provider + type: object + version: + default: '*' + description: Version is the chart version semver expression, ignored + for charts from GitRepository and Bucket sources. Defaults to latest + when omitted. + type: string + required: + - chart + - interval + - sourceRef + type: object + status: + default: + observedGeneration: -1 + description: HelmChartStatus records the observed state of the HelmChart. + properties: + artifact: + description: Artifact represents the output of the last successful + reconciliation. + properties: + digest: + description: Digest is the digest of the file in the form of ':'. + pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ + type: string + lastUpdateTime: + description: LastUpdateTime is the timestamp corresponding to + the last update of the Artifact. + format: date-time + type: string + metadata: + additionalProperties: + type: string + description: Metadata holds upstream information such as OCI annotations. + type: object + path: + description: Path is the relative file path of the Artifact. It + can be used to locate the file in the root of the Artifact storage + on the local file system of the controller managing the Source. + type: string + revision: + description: Revision is a human-readable identifier traceable + in the origin source system. It can be a Git commit SHA, Git + tag, a Helm chart version, etc. + type: string + size: + description: Size is the number of bytes in the file. + format: int64 + type: integer + url: + description: URL is the HTTP address of the Artifact as exposed + by the controller managing the Source. It can be used to retrieve + the Artifact for consumption, e.g. by another controller applying + the Artifact contents. + type: string + required: + - lastUpdateTime + - path + - revision + - url + type: object + conditions: + description: Conditions holds the conditions for the HelmChart. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + lastHandledReconcileAt: + description: LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value can + be detected. + type: string + observedChartName: + description: ObservedChartName is the last observed chart name as + specified by the resolved chart reference. + type: string + observedGeneration: + description: ObservedGeneration is the last observed generation of + the HelmChart object. + format: int64 + type: integer + observedSourceArtifactRevision: + description: ObservedSourceArtifactRevision is the last observed Artifact.Revision + of the HelmChartSpec.SourceRef. + type: string + url: + description: URL is the dynamic fetch link for the latest Artifact. + It is provided on a "best effort" basis, and using the precise BucketStatus.Artifact + data is recommended. + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.0 + labels: + app.kubernetes.io/component: source-controller + app.kubernetes.io/instance: flux-system + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: v2.1.2 + name: helmrepositories.source.toolkit.fluxcd.io +spec: + group: source.toolkit.fluxcd.io + names: + kind: HelmRepository + listKind: HelmRepositoryList + plural: helmrepositories + shortNames: + - helmrepo + singular: helmrepository + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.url + name: URL + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + description: HelmRepository is the Schema for the helmrepositories API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: HelmRepositorySpec defines the reference to a Helm repository. + properties: + accessFrom: + description: AccessFrom defines an Access Control List for allowing + cross-namespace references to this object. + properties: + namespaceSelectors: + description: NamespaceSelectors is the list of namespace selectors + to which this ACL applies. Items in this list are evaluated + using a logical OR operation. + items: + description: NamespaceSelector selects the namespaces to which + this ACL applies. An empty map of MatchLabels matches all + namespaces in a cluster. + properties: + matchLabels: + additionalProperties: + type: string + description: MatchLabels is a map of {key,value} pairs. + A single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field is + "key", the operator is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + type: array + required: + - namespaceSelectors + type: object + interval: + description: The interval at which to check the upstream for updates. + type: string + passCredentials: + description: PassCredentials allows the credentials from the SecretRef + to be passed on to a host that does not match the host as defined + in URL. This may be required if the host of the advertised chart + URLs in the index differ from the defined URL. Enabling this should + be done with caution, as it can potentially result in credentials + getting stolen in a MITM-attack. + type: boolean + secretRef: + description: The name of the secret containing authentication credentials + for the Helm repository. For HTTP/S basic auth the secret must contain + username and password fields. For TLS the secret must contain a + certFile and keyFile, and/or caFile fields. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + suspend: + description: This flag tells the controller to suspend the reconciliation + of this source. + type: boolean + timeout: + default: 60s + description: The timeout of index downloading, defaults to 60s. + type: string + url: + description: The Helm repository URL, a valid URL contains at least + a protocol and host. + type: string + required: + - interval + - url + type: object + status: + default: + observedGeneration: -1 + description: HelmRepositoryStatus defines the observed state of the HelmRepository. + properties: + artifact: + description: Artifact represents the output of the last successful + repository sync. + properties: + checksum: + description: Checksum is the SHA256 checksum of the artifact. + type: string + lastUpdateTime: + description: LastUpdateTime is the timestamp corresponding to + the last update of this artifact. + format: date-time + type: string + path: + description: Path is the relative file path of this artifact. + type: string + revision: + description: Revision is a human readable identifier traceable + in the origin source system. It can be a Git commit SHA, Git + tag, a Helm index timestamp, a Helm chart version, etc. + type: string + url: + description: URL is the HTTP address of this artifact. + type: string + required: + - path + - url + type: object + conditions: + description: Conditions holds the conditions for the HelmRepository. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + lastHandledReconcileAt: + description: LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value can + be detected. + type: string + observedGeneration: + description: ObservedGeneration is the last observed generation. + format: int64 + type: integer + url: + description: URL is the download link for the last index fetched. + type: string + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .spec.url + name: URL + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + name: v1beta2 + schema: + openAPIV3Schema: + description: HelmRepository is the Schema for the helmrepositories API. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: HelmRepositorySpec specifies the required configuration to + produce an Artifact for a Helm repository index YAML. + properties: + accessFrom: + description: 'AccessFrom specifies an Access Control List for allowing + cross-namespace references to this object. NOTE: Not implemented, + provisional as of https://github.com/fluxcd/flux2/pull/2092' + properties: + namespaceSelectors: + description: NamespaceSelectors is the list of namespace selectors + to which this ACL applies. Items in this list are evaluated + using a logical OR operation. + items: + description: NamespaceSelector selects the namespaces to which + this ACL applies. An empty map of MatchLabels matches all + namespaces in a cluster. + properties: + matchLabels: + additionalProperties: + type: string + description: MatchLabels is a map of {key,value} pairs. + A single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field is + "key", the operator is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + type: array + required: + - namespaceSelectors + type: object + certSecretRef: + description: "CertSecretRef can be given the name of a Secret containing + either or both of \n - a PEM-encoded client certificate (`tls.crt`) + and private key (`tls.key`); - a PEM-encoded CA certificate (`ca.crt`) + \n and whichever are supplied, will be used for connecting to the + registry. The client cert and key are useful if you are authenticating + with a certificate; the CA cert is useful if you are using a self-signed + server certificate. The Secret must be of type `Opaque` or `kubernetes.io/tls`. + \n It takes precedence over the values specified in the Secret referred + to by `.spec.secretRef`." + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + interval: + description: Interval at which the HelmRepository URL is checked for + updates. This interval is approximate and may be subject to jitter + to ensure efficient use of resources. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + passCredentials: + description: PassCredentials allows the credentials from the SecretRef + to be passed on to a host that does not match the host as defined + in URL. This may be required if the host of the advertised chart + URLs in the index differ from the defined URL. Enabling this should + be done with caution, as it can potentially result in credentials + getting stolen in a MITM-attack. + type: boolean + provider: + default: generic + description: Provider used for authentication, can be 'aws', 'azure', + 'gcp' or 'generic'. This field is optional, and only taken into + account if the .spec.type field is set to 'oci'. When not specified, + defaults to 'generic'. + enum: + - generic + - aws + - azure + - gcp + type: string + secretRef: + description: SecretRef specifies the Secret containing authentication + credentials for the HelmRepository. For HTTP/S basic auth the secret + must contain 'username' and 'password' fields. Support for TLS auth + using the 'certFile' and 'keyFile', and/or 'caFile' keys is deprecated. + Please use `.spec.certSecretRef` instead. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + suspend: + description: Suspend tells the controller to suspend the reconciliation + of this HelmRepository. + type: boolean + timeout: + default: 60s + description: Timeout is used for the index fetch operation for an + HTTPS helm repository, and for remote OCI Repository operations + like pulling for an OCI helm repository. Its default value is 60s. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$ + type: string + type: + description: Type of the HelmRepository. When this field is set to "oci", + the URL field value must be prefixed with "oci://". + enum: + - default + - oci + type: string + url: + description: URL of the Helm repository, a valid URL contains at least + a protocol and host. + type: string + required: + - interval + - url + type: object + status: + default: + observedGeneration: -1 + description: HelmRepositoryStatus records the observed state of the HelmRepository. + properties: + artifact: + description: Artifact represents the last successful HelmRepository + reconciliation. + properties: + digest: + description: Digest is the digest of the file in the form of ':'. + pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ + type: string + lastUpdateTime: + description: LastUpdateTime is the timestamp corresponding to + the last update of the Artifact. + format: date-time + type: string + metadata: + additionalProperties: + type: string + description: Metadata holds upstream information such as OCI annotations. + type: object + path: + description: Path is the relative file path of the Artifact. It + can be used to locate the file in the root of the Artifact storage + on the local file system of the controller managing the Source. + type: string + revision: + description: Revision is a human-readable identifier traceable + in the origin source system. It can be a Git commit SHA, Git + tag, a Helm chart version, etc. + type: string + size: + description: Size is the number of bytes in the file. + format: int64 + type: integer + url: + description: URL is the HTTP address of the Artifact as exposed + by the controller managing the Source. It can be used to retrieve + the Artifact for consumption, e.g. by another controller applying + the Artifact contents. + type: string + required: + - lastUpdateTime + - path + - revision + - url + type: object + conditions: + description: Conditions holds the conditions for the HelmRepository. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + lastHandledReconcileAt: + description: LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value can + be detected. + type: string + observedGeneration: + description: ObservedGeneration is the last observed generation of + the HelmRepository object. + format: int64 + type: integer + url: + description: URL is the dynamic fetch link for the latest Artifact. + It is provided on a "best effort" basis, and using the precise HelmRepositoryStatus.Artifact + data is recommended. + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.0 + labels: + app.kubernetes.io/component: source-controller + app.kubernetes.io/instance: flux-system + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: v2.1.2 + name: ocirepositories.source.toolkit.fluxcd.io +spec: + group: source.toolkit.fluxcd.io + names: + kind: OCIRepository + listKind: OCIRepositoryList + plural: ocirepositories + shortNames: + - ocirepo + singular: ocirepository + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.url + name: URL + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta2 + schema: + openAPIV3Schema: + description: OCIRepository is the Schema for the ocirepositories API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: OCIRepositorySpec defines the desired state of OCIRepository + properties: + certSecretRef: + description: "CertSecretRef can be given the name of a Secret containing + either or both of \n - a PEM-encoded client certificate (`tls.crt`) + and private key (`tls.key`); - a PEM-encoded CA certificate (`ca.crt`) + \n and whichever are supplied, will be used for connecting to the + registry. The client cert and key are useful if you are authenticating + with a certificate; the CA cert is useful if you are using a self-signed + server certificate. The Secret must be of type `Opaque` or `kubernetes.io/tls`. + \n Note: Support for the `caFile`, `certFile` and `keyFile` keys + have been deprecated." + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + ignore: + description: Ignore overrides the set of excluded patterns in the + .sourceignore format (which is the same as .gitignore). If not provided, + a default will be used, consult the documentation for your version + to find out what those are. + type: string + insecure: + description: Insecure allows connecting to a non-TLS HTTP container + registry. + type: boolean + interval: + description: Interval at which the OCIRepository URL is checked for + updates. This interval is approximate and may be subject to jitter + to ensure efficient use of resources. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + layerSelector: + description: LayerSelector specifies which layer should be extracted + from the OCI artifact. When not specified, the first layer found + in the artifact is selected. + properties: + mediaType: + description: MediaType specifies the OCI media type of the layer + which should be extracted from the OCI Artifact. The first layer + matching this type is selected. + type: string + operation: + description: Operation specifies how the selected layer should + be processed. By default, the layer compressed content is extracted + to storage. When the operation is set to 'copy', the layer compressed + content is persisted to storage as it is. + enum: + - extract + - copy + type: string + type: object + provider: + default: generic + description: The provider used for authentication, can be 'aws', 'azure', + 'gcp' or 'generic'. When not specified, defaults to 'generic'. + enum: + - generic + - aws + - azure + - gcp + type: string + ref: + description: The OCI reference to pull and monitor for changes, defaults + to the latest tag. + properties: + digest: + description: Digest is the image digest to pull, takes precedence + over SemVer. The value should be in the format 'sha256:'. + type: string + semver: + description: SemVer is the range of tags to pull selecting the + latest within the range, takes precedence over Tag. + type: string + tag: + description: Tag is the image tag to pull, defaults to latest. + type: string + type: object + secretRef: + description: SecretRef contains the secret name containing the registry + login credentials to resolve image metadata. The secret must be + of type kubernetes.io/dockerconfigjson. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + serviceAccountName: + description: 'ServiceAccountName is the name of the Kubernetes ServiceAccount + used to authenticate the image pull if the service account has attached + pull secrets. For more information: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#add-imagepullsecrets-to-a-service-account' + type: string + suspend: + description: This flag tells the controller to suspend the reconciliation + of this source. + type: boolean + timeout: + default: 60s + description: The timeout for remote OCI Repository operations like + pulling, defaults to 60s. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$ + type: string + url: + description: URL is a reference to an OCI artifact repository hosted + on a remote container registry. + pattern: ^oci://.*$ + type: string + verify: + description: Verify contains the secret name containing the trusted + public keys used to verify the signature and specifies which provider + to use to check whether OCI image is authentic. + properties: + provider: + default: cosign + description: Provider specifies the technology used to sign the + OCI Artifact. + enum: + - cosign + type: string + secretRef: + description: SecretRef specifies the Kubernetes Secret containing + the trusted public keys. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + required: + - provider + type: object + required: + - interval + - url + type: object + status: + default: + observedGeneration: -1 + description: OCIRepositoryStatus defines the observed state of OCIRepository + properties: + artifact: + description: Artifact represents the output of the last successful + OCI Repository sync. + properties: + digest: + description: Digest is the digest of the file in the form of ':'. + pattern: ^[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+$ + type: string + lastUpdateTime: + description: LastUpdateTime is the timestamp corresponding to + the last update of the Artifact. + format: date-time + type: string + metadata: + additionalProperties: + type: string + description: Metadata holds upstream information such as OCI annotations. + type: object + path: + description: Path is the relative file path of the Artifact. It + can be used to locate the file in the root of the Artifact storage + on the local file system of the controller managing the Source. + type: string + revision: + description: Revision is a human-readable identifier traceable + in the origin source system. It can be a Git commit SHA, Git + tag, a Helm chart version, etc. + type: string + size: + description: Size is the number of bytes in the file. + format: int64 + type: integer + url: + description: URL is the HTTP address of the Artifact as exposed + by the controller managing the Source. It can be used to retrieve + the Artifact for consumption, e.g. by another controller applying + the Artifact contents. + type: string + required: + - lastUpdateTime + - path + - revision + - url + type: object + conditions: + description: Conditions holds the conditions for the OCIRepository. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + contentConfigChecksum: + description: "ContentConfigChecksum is a checksum of all the configurations + related to the content of the source artifact: - .spec.ignore - + .spec.layerSelector observed in .status.observedGeneration version + of the object. This can be used to determine if the content configuration + has changed and the artifact needs to be rebuilt. It has the format + of `:`, for example: `sha256:`. \n Deprecated: + Replaced with explicit fields for observed artifact content config + in the status." + type: string + lastHandledReconcileAt: + description: LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value can + be detected. + type: string + observedGeneration: + description: ObservedGeneration is the last observed generation. + format: int64 + type: integer + observedIgnore: + description: ObservedIgnore is the observed exclusion patterns used + for constructing the source artifact. + type: string + observedLayerSelector: + description: ObservedLayerSelector is the observed layer selector + used for constructing the source artifact. + properties: + mediaType: + description: MediaType specifies the OCI media type of the layer + which should be extracted from the OCI Artifact. The first layer + matching this type is selected. + type: string + operation: + description: Operation specifies how the selected layer should + be processed. By default, the layer compressed content is extracted + to storage. When the operation is set to 'copy', the layer compressed + content is persisted to storage as it is. + enum: + - extract + - copy + type: string + type: object + url: + description: URL is the download link for the artifact output of the + last OCI Repository sync. + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/component: source-controller + app.kubernetes.io/instance: flux-system + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: v2.1.2 + name: source-controller + namespace: flux-system +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/component: source-controller + app.kubernetes.io/instance: flux-system + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: v2.1.2 + control-plane: controller + name: source-controller + namespace: flux-system +spec: + ports: + - name: http + port: 80 + protocol: TCP + targetPort: http + selector: + app: source-controller + type: ClusterIP +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/component: source-controller + app.kubernetes.io/instance: flux-system + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: v2.1.2 + control-plane: controller + name: source-controller + namespace: flux-system +spec: + replicas: 1 + selector: + matchLabels: + app: source-controller + strategy: + type: Recreate + template: + metadata: + annotations: + prometheus.io/port: "8080" + prometheus.io/scrape: "true" + labels: + app: source-controller + spec: + containers: + - args: + - --events-addr=http://notification-controller.flux-system.svc.cluster.local./ + - --watch-all-namespaces=true + - --log-level=info + - --log-encoding=json + - --enable-leader-election + - --storage-path=/data + - --storage-adv-addr=source-controller.$(RUNTIME_NAMESPACE).svc.cluster.local. + env: + - name: RUNTIME_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: TUF_ROOT + value: /tmp/.sigstore + image: ghcr.io/fluxcd/source-controller:v1.1.2 + imagePullPolicy: IfNotPresent + livenessProbe: + httpGet: + path: /healthz + port: healthz + name: manager + ports: + - containerPort: 9090 + name: http + protocol: TCP + - containerPort: 8080 + name: http-prom + protocol: TCP + - containerPort: 9440 + name: healthz + protocol: TCP + readinessProbe: + httpGet: + path: / + port: http + resources: + limits: + cpu: 1000m + memory: 1Gi + requests: + cpu: 50m + memory: 64Mi + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + volumeMounts: + - mountPath: /data + name: data + - mountPath: /tmp + name: tmp + nodeSelector: + kubernetes.io/os: linux + priorityClassName: system-cluster-critical + securityContext: + fsGroup: 1337 + serviceAccountName: source-controller + terminationGracePeriodSeconds: 10 + volumes: + - emptyDir: {} + name: data + - emptyDir: {} + name: tmp +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.0 + labels: + app.kubernetes.io/component: kustomize-controller + app.kubernetes.io/instance: flux-system + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: v2.1.2 + name: kustomizations.kustomize.toolkit.fluxcd.io +spec: + group: kustomize.toolkit.fluxcd.io + names: + kind: Kustomization + listKind: KustomizationList + plural: kustomizations + shortNames: + - ks + singular: kustomization + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + name: v1 + schema: + openAPIV3Schema: + description: Kustomization is the Schema for the kustomizations API. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: KustomizationSpec defines the configuration to calculate + the desired state from a Source using Kustomize. + properties: + commonMetadata: + description: CommonMetadata specifies the common labels and annotations + that are applied to all resources. Any existing label or annotation + will be overridden if its key matches a common one. + properties: + annotations: + additionalProperties: + type: string + description: Annotations to be added to the object's metadata. + type: object + labels: + additionalProperties: + type: string + description: Labels to be added to the object's metadata. + type: object + type: object + components: + description: Components specifies relative paths to specifications + of other Components. + items: + type: string + type: array + decryption: + description: Decrypt Kubernetes secrets before applying them on the + cluster. + properties: + provider: + description: Provider is the name of the decryption engine. + enum: + - sops + type: string + secretRef: + description: The secret name containing the private OpenPGP keys + used for decryption. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + required: + - provider + type: object + dependsOn: + description: DependsOn may contain a meta.NamespacedObjectReference + slice with references to Kustomization resources that must be ready + before this Kustomization can be reconciled. + items: + description: NamespacedObjectReference contains enough information + to locate the referenced Kubernetes resource object in any namespace. + properties: + name: + description: Name of the referent. + type: string + namespace: + description: Namespace of the referent, when not specified it + acts as LocalObjectReference. + type: string + required: + - name + type: object + type: array + force: + default: false + description: Force instructs the controller to recreate resources + when patching fails due to an immutable field change. + type: boolean + healthChecks: + description: A list of resources to be included in the health assessment. + items: + description: NamespacedObjectKindReference contains enough information + to locate the typed referenced Kubernetes resource object in any + namespace. + properties: + apiVersion: + description: API version of the referent, if not specified the + Kubernetes preferred version will be used. + type: string + kind: + description: Kind of the referent. + type: string + name: + description: Name of the referent. + type: string + namespace: + description: Namespace of the referent, when not specified it + acts as LocalObjectReference. + type: string + required: + - kind + - name + type: object + type: array + images: + description: Images is a list of (image name, new name, new tag or + digest) for changing image names, tags or digests. This can also + be achieved with a patch, but this operator is simpler to specify. + items: + description: Image contains an image name, a new name, a new tag + or digest, which will replace the original name and tag. + properties: + digest: + description: Digest is the value used to replace the original + image tag. If digest is present NewTag value is ignored. + type: string + name: + description: Name is a tag-less image name. + type: string + newName: + description: NewName is the value used to replace the original + name. + type: string + newTag: + description: NewTag is the value used to replace the original + tag. + type: string + required: + - name + type: object + type: array + interval: + description: The interval at which to reconcile the Kustomization. + This interval is approximate and may be subject to jitter to ensure + efficient use of resources. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + kubeConfig: + description: The KubeConfig for reconciling the Kustomization on a + remote cluster. When used in combination with KustomizationSpec.ServiceAccountName, + forces the controller to act on behalf of that Service Account at + the target cluster. If the --default-service-account flag is set, + its value will be used as a controller level fallback for when KustomizationSpec.ServiceAccountName + is empty. + properties: + secretRef: + description: SecretRef holds the name of a secret that contains + a key with the kubeconfig file as the value. If no key is set, + the key will default to 'value'. It is recommended that the + kubeconfig is self-contained, and the secret is regularly updated + if credentials such as a cloud-access-token expire. Cloud specific + `cmd-path` auth helpers will not function without adding binaries + and credentials to the Pod that is responsible for reconciling + Kubernetes resources. + properties: + key: + description: Key in the Secret, when not specified an implementation-specific + default key is used. + type: string + name: + description: Name of the Secret. + type: string + required: + - name + type: object + required: + - secretRef + type: object + patches: + description: Strategic merge and JSON patches, defined as inline YAML + objects, capable of targeting objects based on kind, label and annotation + selectors. + items: + description: Patch contains an inline StrategicMerge or JSON6902 + patch, and the target the patch should be applied to. + properties: + patch: + description: Patch contains an inline StrategicMerge patch or + an inline JSON6902 patch with an array of operation objects. + type: string + target: + description: Target points to the resources that the patch document + should be applied to. + properties: + annotationSelector: + description: AnnotationSelector is a string that follows + the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api + It matches with the resource annotations. + type: string + group: + description: Group is the API group to select resources + from. Together with Version and Kind it is capable of + unambiguously identifying and/or selecting resources. + https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + kind: + description: Kind of the API Group to select resources from. + Together with Group and Version it is capable of unambiguously + identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + labelSelector: + description: LabelSelector is a string that follows the + label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api + It matches with the resource labels. + type: string + name: + description: Name to match resources with. + type: string + namespace: + description: Namespace to select resources from. + type: string + version: + description: Version of the API Group to select resources + from. Together with Group and Kind it is capable of unambiguously + identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + type: object + required: + - patch + type: object + type: array + path: + description: Path to the directory containing the kustomization.yaml + file, or the set of plain YAMLs a kustomization.yaml should be generated + for. Defaults to 'None', which translates to the root path of the + SourceRef. + type: string + postBuild: + description: PostBuild describes which actions to perform on the YAML + manifest generated by building the kustomize overlay. + properties: + substitute: + additionalProperties: + type: string + description: Substitute holds a map of key/value pairs. The variables + defined in your YAML manifests that match any of the keys defined + in the map will be substituted with the set value. Includes + support for bash string replacement functions e.g. ${var:=default}, + ${var:position} and ${var/substring/replacement}. + type: object + substituteFrom: + description: SubstituteFrom holds references to ConfigMaps and + Secrets containing the variables and their values to be substituted + in the YAML manifests. The ConfigMap and the Secret data keys + represent the var names, and they must match the vars declared + in the manifests for the substitution to happen. + items: + description: SubstituteReference contains a reference to a resource + containing the variables name and value. + properties: + kind: + description: Kind of the values referent, valid values are + ('Secret', 'ConfigMap'). + enum: + - Secret + - ConfigMap + type: string + name: + description: Name of the values referent. Should reside + in the same namespace as the referring resource. + maxLength: 253 + minLength: 1 + type: string + optional: + default: false + description: Optional indicates whether the referenced resource + must exist, or whether to tolerate its absence. If true + and the referenced resource is absent, proceed as if the + resource was present but empty, without any variables + defined. + type: boolean + required: + - kind + - name + type: object + type: array + type: object + prune: + description: Prune enables garbage collection. + type: boolean + retryInterval: + description: The interval at which to retry a previously failed reconciliation. + When not specified, the controller uses the KustomizationSpec.Interval + value to retry failures. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + serviceAccountName: + description: The name of the Kubernetes service account to impersonate + when reconciling this Kustomization. + type: string + sourceRef: + description: Reference of the source where the kustomization file + is. + properties: + apiVersion: + description: API version of the referent. + type: string + kind: + description: Kind of the referent. + enum: + - OCIRepository + - GitRepository + - Bucket + type: string + name: + description: Name of the referent. + type: string + namespace: + description: Namespace of the referent, defaults to the namespace + of the Kubernetes resource object that contains the reference. + type: string + required: + - kind + - name + type: object + suspend: + description: This flag tells the controller to suspend subsequent + kustomize executions, it does not apply to already started executions. + Defaults to false. + type: boolean + targetNamespace: + description: TargetNamespace sets or overrides the namespace in the + kustomization.yaml file. + maxLength: 63 + minLength: 1 + type: string + timeout: + description: Timeout for validation, apply and health checking operations. + Defaults to 'Interval' duration. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + wait: + description: Wait instructs the controller to check the health of + all the reconciled resources. When enabled, the HealthChecks are + ignored. Defaults to false. + type: boolean + required: + - interval + - prune + - sourceRef + type: object + status: + default: + observedGeneration: -1 + description: KustomizationStatus defines the observed state of a kustomization. + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + inventory: + description: Inventory contains the list of Kubernetes resource object + references that have been successfully applied. + properties: + entries: + description: Entries of Kubernetes resource object references. + items: + description: ResourceRef contains the information necessary + to locate a resource within a cluster. + properties: + id: + description: ID is the string representation of the Kubernetes + resource object's metadata, in the format '___'. + type: string + v: + description: Version is the API version of the Kubernetes + resource object's kind. + type: string + required: + - id + - v + type: object + type: array + required: + - entries + type: object + lastAppliedRevision: + description: The last successfully applied revision. Equals the Revision + of the applied Artifact from the referenced Source. + type: string + lastAttemptedRevision: + description: LastAttemptedRevision is the revision of the last reconciliation + attempt. + type: string + lastHandledReconcileAt: + description: LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value can + be detected. + type: string + observedGeneration: + description: ObservedGeneration is the last reconciled generation. + format: int64 + type: integer + type: object + type: object + served: true + storage: true + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + deprecated: true + deprecationWarning: v1beta1 Kustomization is deprecated, upgrade to v1 + name: v1beta1 + schema: + openAPIV3Schema: + description: Kustomization is the Schema for the kustomizations API. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: KustomizationSpec defines the desired state of a kustomization. + properties: + decryption: + description: Decrypt Kubernetes secrets before applying them on the + cluster. + properties: + provider: + description: Provider is the name of the decryption engine. + enum: + - sops + type: string + secretRef: + description: The secret name containing the private OpenPGP keys + used for decryption. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + required: + - provider + type: object + dependsOn: + description: DependsOn may contain a meta.NamespacedObjectReference + slice with references to Kustomization resources that must be ready + before this Kustomization can be reconciled. + items: + description: NamespacedObjectReference contains enough information + to locate the referenced Kubernetes resource object in any namespace. + properties: + name: + description: Name of the referent. + type: string + namespace: + description: Namespace of the referent, when not specified it + acts as LocalObjectReference. + type: string + required: + - name + type: object + type: array + force: + default: false + description: Force instructs the controller to recreate resources + when patching fails due to an immutable field change. + type: boolean + healthChecks: + description: A list of resources to be included in the health assessment. + items: + description: NamespacedObjectKindReference contains enough information + to locate the typed referenced Kubernetes resource object in any + namespace. + properties: + apiVersion: + description: API version of the referent, if not specified the + Kubernetes preferred version will be used. + type: string + kind: + description: Kind of the referent. + type: string + name: + description: Name of the referent. + type: string + namespace: + description: Namespace of the referent, when not specified it + acts as LocalObjectReference. + type: string + required: + - kind + - name + type: object + type: array + images: + description: Images is a list of (image name, new name, new tag or + digest) for changing image names, tags or digests. This can also + be achieved with a patch, but this operator is simpler to specify. + items: + description: Image contains an image name, a new name, a new tag + or digest, which will replace the original name and tag. + properties: + digest: + description: Digest is the value used to replace the original + image tag. If digest is present NewTag value is ignored. + type: string + name: + description: Name is a tag-less image name. + type: string + newName: + description: NewName is the value used to replace the original + name. + type: string + newTag: + description: NewTag is the value used to replace the original + tag. + type: string + required: + - name + type: object + type: array + interval: + description: The interval at which to reconcile the Kustomization. + type: string + kubeConfig: + description: The KubeConfig for reconciling the Kustomization on a + remote cluster. When specified, KubeConfig takes precedence over + ServiceAccountName. + properties: + secretRef: + description: SecretRef holds the name to a secret that contains + a 'value' key with the kubeconfig file as the value. It must + be in the same namespace as the Kustomization. It is recommended + that the kubeconfig is self-contained, and the secret is regularly + updated if credentials such as a cloud-access-token expire. + Cloud specific `cmd-path` auth helpers will not function without + adding binaries and credentials to the Pod that is responsible + for reconciling the Kustomization. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + type: object + patches: + description: Strategic merge and JSON patches, defined as inline YAML + objects, capable of targeting objects based on kind, label and annotation + selectors. + items: + description: Patch contains an inline StrategicMerge or JSON6902 + patch, and the target the patch should be applied to. + properties: + patch: + description: Patch contains an inline StrategicMerge patch or + an inline JSON6902 patch with an array of operation objects. + type: string + target: + description: Target points to the resources that the patch document + should be applied to. + properties: + annotationSelector: + description: AnnotationSelector is a string that follows + the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api + It matches with the resource annotations. + type: string + group: + description: Group is the API group to select resources + from. Together with Version and Kind it is capable of + unambiguously identifying and/or selecting resources. + https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + kind: + description: Kind of the API Group to select resources from. + Together with Group and Version it is capable of unambiguously + identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + labelSelector: + description: LabelSelector is a string that follows the + label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api + It matches with the resource labels. + type: string + name: + description: Name to match resources with. + type: string + namespace: + description: Namespace to select resources from. + type: string + version: + description: Version of the API Group to select resources + from. Together with Group and Kind it is capable of unambiguously + identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + type: object + required: + - patch + type: object + type: array + patchesJson6902: + description: JSON 6902 patches, defined as inline YAML objects. + items: + description: JSON6902Patch contains a JSON6902 patch and the target + the patch should be applied to. + properties: + patch: + description: Patch contains the JSON6902 patch document with + an array of operation objects. + items: + description: JSON6902 is a JSON6902 operation object. https://datatracker.ietf.org/doc/html/rfc6902#section-4 + properties: + from: + description: From contains a JSON-pointer value that references + a location within the target document where the operation + is performed. The meaning of the value depends on the + value of Op, and is NOT taken into account by all operations. + type: string + op: + description: Op indicates the operation to perform. Its + value MUST be one of "add", "remove", "replace", "move", + "copy", or "test". https://datatracker.ietf.org/doc/html/rfc6902#section-4 + enum: + - test + - remove + - add + - replace + - move + - copy + type: string + path: + description: Path contains the JSON-pointer value that + references a location within the target document where + the operation is performed. The meaning of the value + depends on the value of Op. + type: string + value: + description: Value contains a valid JSON structure. The + meaning of the value depends on the value of Op, and + is NOT taken into account by all operations. + x-kubernetes-preserve-unknown-fields: true + required: + - op + - path + type: object + type: array + target: + description: Target points to the resources that the patch document + should be applied to. + properties: + annotationSelector: + description: AnnotationSelector is a string that follows + the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api + It matches with the resource annotations. + type: string + group: + description: Group is the API group to select resources + from. Together with Version and Kind it is capable of + unambiguously identifying and/or selecting resources. + https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + kind: + description: Kind of the API Group to select resources from. + Together with Group and Version it is capable of unambiguously + identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + labelSelector: + description: LabelSelector is a string that follows the + label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api + It matches with the resource labels. + type: string + name: + description: Name to match resources with. + type: string + namespace: + description: Namespace to select resources from. + type: string + version: + description: Version of the API Group to select resources + from. Together with Group and Kind it is capable of unambiguously + identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + type: object + required: + - patch + - target + type: object + type: array + patchesStrategicMerge: + description: Strategic merge patches, defined as inline YAML objects. + items: + x-kubernetes-preserve-unknown-fields: true + type: array + path: + description: Path to the directory containing the kustomization.yaml + file, or the set of plain YAMLs a kustomization.yaml should be generated + for. Defaults to 'None', which translates to the root path of the + SourceRef. + type: string + postBuild: + description: PostBuild describes which actions to perform on the YAML + manifest generated by building the kustomize overlay. + properties: + substitute: + additionalProperties: + type: string + description: Substitute holds a map of key/value pairs. The variables + defined in your YAML manifests that match any of the keys defined + in the map will be substituted with the set value. Includes + support for bash string replacement functions e.g. ${var:=default}, + ${var:position} and ${var/substring/replacement}. + type: object + substituteFrom: + description: SubstituteFrom holds references to ConfigMaps and + Secrets containing the variables and their values to be substituted + in the YAML manifests. The ConfigMap and the Secret data keys + represent the var names and they must match the vars declared + in the manifests for the substitution to happen. + items: + description: SubstituteReference contains a reference to a resource + containing the variables name and value. + properties: + kind: + description: Kind of the values referent, valid values are + ('Secret', 'ConfigMap'). + enum: + - Secret + - ConfigMap + type: string + name: + description: Name of the values referent. Should reside + in the same namespace as the referring resource. + maxLength: 253 + minLength: 1 + type: string + required: + - kind + - name + type: object + type: array + type: object + prune: + description: Prune enables garbage collection. + type: boolean + retryInterval: + description: The interval at which to retry a previously failed reconciliation. + When not specified, the controller uses the KustomizationSpec.Interval + value to retry failures. + type: string + serviceAccountName: + description: The name of the Kubernetes service account to impersonate + when reconciling this Kustomization. + type: string + sourceRef: + description: Reference of the source where the kustomization file + is. + properties: + apiVersion: + description: API version of the referent + type: string + kind: + description: Kind of the referent + enum: + - GitRepository + - Bucket + type: string + name: + description: Name of the referent + type: string + namespace: + description: Namespace of the referent, defaults to the Kustomization + namespace + type: string + required: + - kind + - name + type: object + suspend: + description: This flag tells the controller to suspend subsequent + kustomize executions, it does not apply to already started executions. + Defaults to false. + type: boolean + targetNamespace: + description: TargetNamespace sets or overrides the namespace in the + kustomization.yaml file. + maxLength: 63 + minLength: 1 + type: string + timeout: + description: Timeout for validation, apply and health checking operations. + Defaults to 'Interval' duration. + type: string + validation: + description: Validate the Kubernetes objects before applying them + on the cluster. The validation strategy can be 'client' (local dry-run), + 'server' (APIServer dry-run) or 'none'. When 'Force' is 'true', + validation will fallback to 'client' if set to 'server' because + server-side validation is not supported in this scenario. + enum: + - none + - client + - server + type: string + required: + - interval + - prune + - sourceRef + type: object + status: + default: + observedGeneration: -1 + description: KustomizationStatus defines the observed state of a kustomization. + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + lastAppliedRevision: + description: The last successfully applied revision. The revision + format for Git sources is /. + type: string + lastAttemptedRevision: + description: LastAttemptedRevision is the revision of the last reconciliation + attempt. + type: string + lastHandledReconcileAt: + description: LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value can + be detected. + type: string + observedGeneration: + description: ObservedGeneration is the last reconciled generation. + format: int64 + type: integer + snapshot: + description: The last successfully applied revision metadata. + properties: + checksum: + description: The manifests sha1 checksum. + type: string + entries: + description: A list of Kubernetes kinds grouped by namespace. + items: + description: Snapshot holds the metadata of namespaced Kubernetes + objects + properties: + kinds: + additionalProperties: + type: string + description: The list of Kubernetes kinds. + type: object + namespace: + description: The namespace of this entry. + type: string + required: + - kinds + type: object + type: array + required: + - checksum + - entries + type: object + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + deprecated: true + deprecationWarning: v1beta2 Kustomization is deprecated, upgrade to v1 + name: v1beta2 + schema: + openAPIV3Schema: + description: Kustomization is the Schema for the kustomizations API. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: KustomizationSpec defines the configuration to calculate + the desired state from a Source using Kustomize. + properties: + commonMetadata: + description: CommonMetadata specifies the common labels and annotations + that are applied to all resources. Any existing label or annotation + will be overridden if its key matches a common one. + properties: + annotations: + additionalProperties: + type: string + description: Annotations to be added to the object's metadata. + type: object + labels: + additionalProperties: + type: string + description: Labels to be added to the object's metadata. + type: object + type: object + components: + description: Components specifies relative paths to specifications + of other Components. + items: + type: string + type: array + decryption: + description: Decrypt Kubernetes secrets before applying them on the + cluster. + properties: + provider: + description: Provider is the name of the decryption engine. + enum: + - sops + type: string + secretRef: + description: The secret name containing the private OpenPGP keys + used for decryption. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + required: + - provider + type: object + dependsOn: + description: DependsOn may contain a meta.NamespacedObjectReference + slice with references to Kustomization resources that must be ready + before this Kustomization can be reconciled. + items: + description: NamespacedObjectReference contains enough information + to locate the referenced Kubernetes resource object in any namespace. + properties: + name: + description: Name of the referent. + type: string + namespace: + description: Namespace of the referent, when not specified it + acts as LocalObjectReference. + type: string + required: + - name + type: object + type: array + force: + default: false + description: Force instructs the controller to recreate resources + when patching fails due to an immutable field change. + type: boolean + healthChecks: + description: A list of resources to be included in the health assessment. + items: + description: NamespacedObjectKindReference contains enough information + to locate the typed referenced Kubernetes resource object in any + namespace. + properties: + apiVersion: + description: API version of the referent, if not specified the + Kubernetes preferred version will be used. + type: string + kind: + description: Kind of the referent. + type: string + name: + description: Name of the referent. + type: string + namespace: + description: Namespace of the referent, when not specified it + acts as LocalObjectReference. + type: string + required: + - kind + - name + type: object + type: array + images: + description: Images is a list of (image name, new name, new tag or + digest) for changing image names, tags or digests. This can also + be achieved with a patch, but this operator is simpler to specify. + items: + description: Image contains an image name, a new name, a new tag + or digest, which will replace the original name and tag. + properties: + digest: + description: Digest is the value used to replace the original + image tag. If digest is present NewTag value is ignored. + type: string + name: + description: Name is a tag-less image name. + type: string + newName: + description: NewName is the value used to replace the original + name. + type: string + newTag: + description: NewTag is the value used to replace the original + tag. + type: string + required: + - name + type: object + type: array + interval: + description: The interval at which to reconcile the Kustomization. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + kubeConfig: + description: The KubeConfig for reconciling the Kustomization on a + remote cluster. When used in combination with KustomizationSpec.ServiceAccountName, + forces the controller to act on behalf of that Service Account at + the target cluster. If the --default-service-account flag is set, + its value will be used as a controller level fallback for when KustomizationSpec.ServiceAccountName + is empty. + properties: + secretRef: + description: SecretRef holds the name of a secret that contains + a key with the kubeconfig file as the value. If no key is set, + the key will default to 'value'. It is recommended that the + kubeconfig is self-contained, and the secret is regularly updated + if credentials such as a cloud-access-token expire. Cloud specific + `cmd-path` auth helpers will not function without adding binaries + and credentials to the Pod that is responsible for reconciling + Kubernetes resources. + properties: + key: + description: Key in the Secret, when not specified an implementation-specific + default key is used. + type: string + name: + description: Name of the Secret. + type: string + required: + - name + type: object + required: + - secretRef + type: object + patches: + description: Strategic merge and JSON patches, defined as inline YAML + objects, capable of targeting objects based on kind, label and annotation + selectors. + items: + description: Patch contains an inline StrategicMerge or JSON6902 + patch, and the target the patch should be applied to. + properties: + patch: + description: Patch contains an inline StrategicMerge patch or + an inline JSON6902 patch with an array of operation objects. + type: string + target: + description: Target points to the resources that the patch document + should be applied to. + properties: + annotationSelector: + description: AnnotationSelector is a string that follows + the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api + It matches with the resource annotations. + type: string + group: + description: Group is the API group to select resources + from. Together with Version and Kind it is capable of + unambiguously identifying and/or selecting resources. + https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + kind: + description: Kind of the API Group to select resources from. + Together with Group and Version it is capable of unambiguously + identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + labelSelector: + description: LabelSelector is a string that follows the + label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api + It matches with the resource labels. + type: string + name: + description: Name to match resources with. + type: string + namespace: + description: Namespace to select resources from. + type: string + version: + description: Version of the API Group to select resources + from. Together with Group and Kind it is capable of unambiguously + identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + type: object + required: + - patch + type: object + type: array + patchesJson6902: + description: 'JSON 6902 patches, defined as inline YAML objects. Deprecated: + Use Patches instead.' + items: + description: JSON6902Patch contains a JSON6902 patch and the target + the patch should be applied to. + properties: + patch: + description: Patch contains the JSON6902 patch document with + an array of operation objects. + items: + description: JSON6902 is a JSON6902 operation object. https://datatracker.ietf.org/doc/html/rfc6902#section-4 + properties: + from: + description: From contains a JSON-pointer value that references + a location within the target document where the operation + is performed. The meaning of the value depends on the + value of Op, and is NOT taken into account by all operations. + type: string + op: + description: Op indicates the operation to perform. Its + value MUST be one of "add", "remove", "replace", "move", + "copy", or "test". https://datatracker.ietf.org/doc/html/rfc6902#section-4 + enum: + - test + - remove + - add + - replace + - move + - copy + type: string + path: + description: Path contains the JSON-pointer value that + references a location within the target document where + the operation is performed. The meaning of the value + depends on the value of Op. + type: string + value: + description: Value contains a valid JSON structure. The + meaning of the value depends on the value of Op, and + is NOT taken into account by all operations. + x-kubernetes-preserve-unknown-fields: true + required: + - op + - path + type: object + type: array + target: + description: Target points to the resources that the patch document + should be applied to. + properties: + annotationSelector: + description: AnnotationSelector is a string that follows + the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api + It matches with the resource annotations. + type: string + group: + description: Group is the API group to select resources + from. Together with Version and Kind it is capable of + unambiguously identifying and/or selecting resources. + https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + kind: + description: Kind of the API Group to select resources from. + Together with Group and Version it is capable of unambiguously + identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + labelSelector: + description: LabelSelector is a string that follows the + label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api + It matches with the resource labels. + type: string + name: + description: Name to match resources with. + type: string + namespace: + description: Namespace to select resources from. + type: string + version: + description: Version of the API Group to select resources + from. Together with Group and Kind it is capable of unambiguously + identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + type: object + required: + - patch + - target + type: object + type: array + patchesStrategicMerge: + description: 'Strategic merge patches, defined as inline YAML objects. + Deprecated: Use Patches instead.' + items: + x-kubernetes-preserve-unknown-fields: true + type: array + path: + description: Path to the directory containing the kustomization.yaml + file, or the set of plain YAMLs a kustomization.yaml should be generated + for. Defaults to 'None', which translates to the root path of the + SourceRef. + type: string + postBuild: + description: PostBuild describes which actions to perform on the YAML + manifest generated by building the kustomize overlay. + properties: + substitute: + additionalProperties: + type: string + description: Substitute holds a map of key/value pairs. The variables + defined in your YAML manifests that match any of the keys defined + in the map will be substituted with the set value. Includes + support for bash string replacement functions e.g. ${var:=default}, + ${var:position} and ${var/substring/replacement}. + type: object + substituteFrom: + description: SubstituteFrom holds references to ConfigMaps and + Secrets containing the variables and their values to be substituted + in the YAML manifests. The ConfigMap and the Secret data keys + represent the var names and they must match the vars declared + in the manifests for the substitution to happen. + items: + description: SubstituteReference contains a reference to a resource + containing the variables name and value. + properties: + kind: + description: Kind of the values referent, valid values are + ('Secret', 'ConfigMap'). + enum: + - Secret + - ConfigMap + type: string + name: + description: Name of the values referent. Should reside + in the same namespace as the referring resource. + maxLength: 253 + minLength: 1 + type: string + optional: + default: false + description: Optional indicates whether the referenced resource + must exist, or whether to tolerate its absence. If true + and the referenced resource is absent, proceed as if the + resource was present but empty, without any variables + defined. + type: boolean + required: + - kind + - name + type: object + type: array + type: object + prune: + description: Prune enables garbage collection. + type: boolean + retryInterval: + description: The interval at which to retry a previously failed reconciliation. + When not specified, the controller uses the KustomizationSpec.Interval + value to retry failures. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + serviceAccountName: + description: The name of the Kubernetes service account to impersonate + when reconciling this Kustomization. + type: string + sourceRef: + description: Reference of the source where the kustomization file + is. + properties: + apiVersion: + description: API version of the referent. + type: string + kind: + description: Kind of the referent. + enum: + - OCIRepository + - GitRepository + - Bucket + type: string + name: + description: Name of the referent. + type: string + namespace: + description: Namespace of the referent, defaults to the namespace + of the Kubernetes resource object that contains the reference. + type: string + required: + - kind + - name + type: object + suspend: + description: This flag tells the controller to suspend subsequent + kustomize executions, it does not apply to already started executions. + Defaults to false. + type: boolean + targetNamespace: + description: TargetNamespace sets or overrides the namespace in the + kustomization.yaml file. + maxLength: 63 + minLength: 1 + type: string + timeout: + description: Timeout for validation, apply and health checking operations. + Defaults to 'Interval' duration. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + validation: + description: 'Deprecated: Not used in v1beta2.' + enum: + - none + - client + - server + type: string + wait: + description: Wait instructs the controller to check the health of + all the reconciled resources. When enabled, the HealthChecks are + ignored. Defaults to false. + type: boolean + required: + - interval + - prune + - sourceRef + type: object + status: + default: + observedGeneration: -1 + description: KustomizationStatus defines the observed state of a kustomization. + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + inventory: + description: Inventory contains the list of Kubernetes resource object + references that have been successfully applied. + properties: + entries: + description: Entries of Kubernetes resource object references. + items: + description: ResourceRef contains the information necessary + to locate a resource within a cluster. + properties: + id: + description: ID is the string representation of the Kubernetes + resource object's metadata, in the format '___'. + type: string + v: + description: Version is the API version of the Kubernetes + resource object's kind. + type: string + required: + - id + - v + type: object + type: array + required: + - entries + type: object + lastAppliedRevision: + description: The last successfully applied revision. Equals the Revision + of the applied Artifact from the referenced Source. + type: string + lastAttemptedRevision: + description: LastAttemptedRevision is the revision of the last reconciliation + attempt. + type: string + lastHandledReconcileAt: + description: LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value can + be detected. + type: string + observedGeneration: + description: ObservedGeneration is the last reconciled generation. + format: int64 + type: integer + type: object + type: object + served: true + storage: false + subresources: + status: {} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/component: kustomize-controller + app.kubernetes.io/instance: flux-system + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: v2.1.2 + name: kustomize-controller + namespace: flux-system +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/component: kustomize-controller + app.kubernetes.io/instance: flux-system + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: v2.1.2 + control-plane: controller + name: kustomize-controller + namespace: flux-system +spec: + replicas: 1 + selector: + matchLabels: + app: kustomize-controller + template: + metadata: + annotations: + prometheus.io/port: "8080" + prometheus.io/scrape: "true" + labels: + app: kustomize-controller + spec: + containers: + - args: + - --events-addr=http://notification-controller.flux-system.svc.cluster.local./ + - --watch-all-namespaces=true + - --log-level=info + - --log-encoding=json + - --enable-leader-election + env: + - name: RUNTIME_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + image: ghcr.io/fluxcd/kustomize-controller:v1.1.1 + imagePullPolicy: IfNotPresent + livenessProbe: + httpGet: + path: /healthz + port: healthz + name: manager + ports: + - containerPort: 8080 + name: http-prom + protocol: TCP + - containerPort: 9440 + name: healthz + protocol: TCP + readinessProbe: + httpGet: + path: /readyz + port: healthz + resources: + limits: + cpu: 1000m + memory: 1Gi + requests: + cpu: 100m + memory: 64Mi + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + volumeMounts: + - mountPath: /tmp + name: temp + nodeSelector: + kubernetes.io/os: linux + priorityClassName: system-cluster-critical + securityContext: + fsGroup: 1337 + serviceAccountName: kustomize-controller + terminationGracePeriodSeconds: 60 + volumes: + - emptyDir: {} + name: temp +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.0 + labels: + app.kubernetes.io/component: helm-controller + app.kubernetes.io/instance: flux-system + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: v2.1.2 + name: helmreleases.helm.toolkit.fluxcd.io +spec: + group: helm.toolkit.fluxcd.io + names: + kind: HelmRelease + listKind: HelmReleaseList + plural: helmreleases + shortNames: + - hr + singular: helmrelease + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + name: v2beta1 + schema: + openAPIV3Schema: + description: HelmRelease is the Schema for the helmreleases API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: HelmReleaseSpec defines the desired state of a Helm release. + properties: + chart: + description: Chart defines the template of the v1beta2.HelmChart that + should be created for this HelmRelease. + properties: + metadata: + description: ObjectMeta holds the template for metadata like labels + and annotations. + properties: + annotations: + additionalProperties: + type: string + description: 'Annotations is an unstructured key value map + stored with a resource that may be set by external tools + to store and retrieve arbitrary metadata. They are not queryable + and should be preserved when modifying objects. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/' + type: object + labels: + additionalProperties: + type: string + description: 'Map of string keys and values that can be used + to organize and categorize (scope and select) objects. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/' + type: object + type: object + spec: + description: Spec holds the template for the v1beta2.HelmChartSpec + for this HelmRelease. + properties: + chart: + description: The name or path the Helm chart is available + at in the SourceRef. + type: string + interval: + description: Interval at which to check the v1beta2.Source + for updates. Defaults to 'HelmReleaseSpec.Interval'. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + reconcileStrategy: + default: ChartVersion + description: Determines what enables the creation of a new + artifact. Valid values are ('ChartVersion', 'Revision'). + See the documentation of the values for an explanation on + their behavior. Defaults to ChartVersion when omitted. + enum: + - ChartVersion + - Revision + type: string + sourceRef: + description: The name and namespace of the v1beta2.Source + the chart is available at. + properties: + apiVersion: + description: APIVersion of the referent. + type: string + kind: + description: Kind of the referent. + enum: + - HelmRepository + - GitRepository + - Bucket + type: string + name: + description: Name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: Namespace of the referent. + maxLength: 63 + minLength: 1 + type: string + required: + - name + type: object + valuesFile: + description: Alternative values file to use as the default + chart values, expected to be a relative path in the SourceRef. + Deprecated in favor of ValuesFiles, for backwards compatibility + the file defined here is merged before the ValuesFiles items. + Ignored when omitted. + type: string + valuesFiles: + description: Alternative list of values files to use as the + chart values (values.yaml is not included by default), expected + to be a relative path in the SourceRef. Values files are + merged in the order of this list with the last file overriding + the first. Ignored when omitted. + items: + type: string + type: array + verify: + description: Verify contains the secret name containing the + trusted public keys used to verify the signature and specifies + which provider to use to check whether OCI image is authentic. + This field is only supported for OCI sources. Chart dependencies, + which are not bundled in the umbrella chart artifact, are + not verified. + properties: + provider: + default: cosign + description: Provider specifies the technology used to + sign the OCI Helm chart. + enum: + - cosign + type: string + secretRef: + description: SecretRef specifies the Kubernetes Secret + containing the trusted public keys. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + required: + - provider + type: object + version: + default: '*' + description: Version semver expression, ignored for charts + from v1beta2.GitRepository and v1beta2.Bucket sources. Defaults + to latest when omitted. + type: string + required: + - chart + - sourceRef + type: object + required: + - spec + type: object + dependsOn: + description: DependsOn may contain a meta.NamespacedObjectReference + slice with references to HelmRelease resources that must be ready + before this HelmRelease can be reconciled. + items: + description: NamespacedObjectReference contains enough information + to locate the referenced Kubernetes resource object in any namespace. + properties: + name: + description: Name of the referent. + type: string + namespace: + description: Namespace of the referent, when not specified it + acts as LocalObjectReference. + type: string + required: + - name + type: object + type: array + install: + description: Install holds the configuration for Helm install actions + for this HelmRelease. + properties: + crds: + description: "CRDs upgrade CRDs from the Helm Chart's crds directory + according to the CRD upgrade policy provided here. Valid values + are `Skip`, `Create` or `CreateReplace`. Default is `Create` + and if omitted CRDs are installed but not updated. \n Skip: + do neither install nor replace (update) any CRDs. \n Create: + new CRDs are created, existing CRDs are neither updated nor + deleted. \n CreateReplace: new CRDs are created, existing CRDs + are updated (replaced) but not deleted. \n By default, CRDs + are applied (installed) during Helm install action. With this + option users can opt-in to CRD replace existing CRDs on Helm + install actions, which is not (yet) natively supported by Helm. + https://helm.sh/docs/chart_best_practices/custom_resource_definitions." + enum: + - Skip + - Create + - CreateReplace + type: string + createNamespace: + description: CreateNamespace tells the Helm install action to + create the HelmReleaseSpec.TargetNamespace if it does not exist + yet. On uninstall, the namespace will not be garbage collected. + type: boolean + disableHooks: + description: DisableHooks prevents hooks from running during the + Helm install action. + type: boolean + disableOpenAPIValidation: + description: DisableOpenAPIValidation prevents the Helm install + action from validating rendered templates against the Kubernetes + OpenAPI Schema. + type: boolean + disableWait: + description: DisableWait disables the waiting for resources to + be ready after a Helm install has been performed. + type: boolean + disableWaitForJobs: + description: DisableWaitForJobs disables waiting for jobs to complete + after a Helm install has been performed. + type: boolean + remediation: + description: Remediation holds the remediation configuration for + when the Helm install action for the HelmRelease fails. The + default is to not perform any action. + properties: + ignoreTestFailures: + description: IgnoreTestFailures tells the controller to skip + remediation when the Helm tests are run after an install + action but fail. Defaults to 'Test.IgnoreFailures'. + type: boolean + remediateLastFailure: + description: RemediateLastFailure tells the controller to + remediate the last failure, when no retries remain. Defaults + to 'false'. + type: boolean + retries: + description: Retries is the number of retries that should + be attempted on failures before bailing. Remediation, using + an uninstall, is performed between each attempt. Defaults + to '0', a negative integer equals to unlimited retries. + type: integer + type: object + replace: + description: Replace tells the Helm install action to re-use the + 'ReleaseName', but only if that name is a deleted release which + remains in the history. + type: boolean + skipCRDs: + description: "SkipCRDs tells the Helm install action to not install + any CRDs. By default, CRDs are installed if not already present. + \n Deprecated use CRD policy (`crds`) attribute with value `Skip` + instead." + type: boolean + timeout: + description: Timeout is the time to wait for any individual Kubernetes + operation (like Jobs for hooks) during the performance of a + Helm install action. Defaults to 'HelmReleaseSpec.Timeout'. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + type: object + interval: + description: Interval at which to reconcile the Helm release. This + interval is approximate and may be subject to jitter to ensure efficient + use of resources. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + kubeConfig: + description: KubeConfig for reconciling the HelmRelease on a remote + cluster. When used in combination with HelmReleaseSpec.ServiceAccountName, + forces the controller to act on behalf of that Service Account at + the target cluster. If the --default-service-account flag is set, + its value will be used as a controller level fallback for when HelmReleaseSpec.ServiceAccountName + is empty. + properties: + secretRef: + description: SecretRef holds the name of a secret that contains + a key with the kubeconfig file as the value. If no key is set, + the key will default to 'value'. It is recommended that the + kubeconfig is self-contained, and the secret is regularly updated + if credentials such as a cloud-access-token expire. Cloud specific + `cmd-path` auth helpers will not function without adding binaries + and credentials to the Pod that is responsible for reconciling + Kubernetes resources. + properties: + key: + description: Key in the Secret, when not specified an implementation-specific + default key is used. + type: string + name: + description: Name of the Secret. + type: string + required: + - name + type: object + required: + - secretRef + type: object + maxHistory: + description: MaxHistory is the number of revisions saved by Helm for + this HelmRelease. Use '0' for an unlimited number of revisions; + defaults to '10'. + type: integer + persistentClient: + description: "PersistentClient tells the controller to use a persistent + Kubernetes client for this release. When enabled, the client will + be reused for the duration of the reconciliation, instead of being + created and destroyed for each (step of a) Helm action. \n This + can improve performance, but may cause issues with some Helm charts + that for example do create Custom Resource Definitions during installation + outside Helm's CRD lifecycle hooks, which are then not observed + to be available by e.g. post-install hooks. \n If not set, it defaults + to true." + type: boolean + postRenderers: + description: PostRenderers holds an array of Helm PostRenderers, which + will be applied in order of their definition. + items: + description: PostRenderer contains a Helm PostRenderer specification. + properties: + kustomize: + description: Kustomization to apply as PostRenderer. + properties: + images: + description: Images is a list of (image name, new name, + new tag or digest) for changing image names, tags or digests. + This can also be achieved with a patch, but this operator + is simpler to specify. + items: + description: Image contains an image name, a new name, + a new tag or digest, which will replace the original + name and tag. + properties: + digest: + description: Digest is the value used to replace the + original image tag. If digest is present NewTag + value is ignored. + type: string + name: + description: Name is a tag-less image name. + type: string + newName: + description: NewName is the value used to replace + the original name. + type: string + newTag: + description: NewTag is the value used to replace the + original tag. + type: string + required: + - name + type: object + type: array + patches: + description: Strategic merge and JSON patches, defined as + inline YAML objects, capable of targeting objects based + on kind, label and annotation selectors. + items: + description: Patch contains an inline StrategicMerge or + JSON6902 patch, and the target the patch should be applied + to. + properties: + patch: + description: Patch contains an inline StrategicMerge + patch or an inline JSON6902 patch with an array + of operation objects. + type: string + target: + description: Target points to the resources that the + patch document should be applied to. + properties: + annotationSelector: + description: AnnotationSelector is a string that + follows the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api + It matches with the resource annotations. + type: string + group: + description: Group is the API group to select + resources from. Together with Version and Kind + it is capable of unambiguously identifying and/or + selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + kind: + description: Kind of the API Group to select resources + from. Together with Group and Version it is + capable of unambiguously identifying and/or + selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + labelSelector: + description: LabelSelector is a string that follows + the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api + It matches with the resource labels. + type: string + name: + description: Name to match resources with. + type: string + namespace: + description: Namespace to select resources from. + type: string + version: + description: Version of the API Group to select + resources from. Together with Group and Kind + it is capable of unambiguously identifying and/or + selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + type: object + required: + - patch + type: object + type: array + patchesJson6902: + description: JSON 6902 patches, defined as inline YAML objects. + items: + description: JSON6902Patch contains a JSON6902 patch and + the target the patch should be applied to. + properties: + patch: + description: Patch contains the JSON6902 patch document + with an array of operation objects. + items: + description: JSON6902 is a JSON6902 operation object. + https://datatracker.ietf.org/doc/html/rfc6902#section-4 + properties: + from: + description: From contains a JSON-pointer value + that references a location within the target + document where the operation is performed. + The meaning of the value depends on the value + of Op, and is NOT taken into account by all + operations. + type: string + op: + description: Op indicates the operation to perform. + Its value MUST be one of "add", "remove", + "replace", "move", "copy", or "test". https://datatracker.ietf.org/doc/html/rfc6902#section-4 + enum: + - test + - remove + - add + - replace + - move + - copy + type: string + path: + description: Path contains the JSON-pointer + value that references a location within the + target document where the operation is performed. + The meaning of the value depends on the value + of Op. + type: string + value: + description: Value contains a valid JSON structure. + The meaning of the value depends on the value + of Op, and is NOT taken into account by all + operations. + x-kubernetes-preserve-unknown-fields: true + required: + - op + - path + type: object + type: array + target: + description: Target points to the resources that the + patch document should be applied to. + properties: + annotationSelector: + description: AnnotationSelector is a string that + follows the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api + It matches with the resource annotations. + type: string + group: + description: Group is the API group to select + resources from. Together with Version and Kind + it is capable of unambiguously identifying and/or + selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + kind: + description: Kind of the API Group to select resources + from. Together with Group and Version it is + capable of unambiguously identifying and/or + selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + labelSelector: + description: LabelSelector is a string that follows + the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api + It matches with the resource labels. + type: string + name: + description: Name to match resources with. + type: string + namespace: + description: Namespace to select resources from. + type: string + version: + description: Version of the API Group to select + resources from. Together with Group and Kind + it is capable of unambiguously identifying and/or + selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + type: object + required: + - patch + - target + type: object + type: array + patchesStrategicMerge: + description: Strategic merge patches, defined as inline + YAML objects. + items: + x-kubernetes-preserve-unknown-fields: true + type: array + type: object + type: object + type: array + releaseName: + description: ReleaseName used for the Helm release. Defaults to a + composition of '[TargetNamespace-]Name'. + maxLength: 53 + minLength: 1 + type: string + rollback: + description: Rollback holds the configuration for Helm rollback actions + for this HelmRelease. + properties: + cleanupOnFail: + description: CleanupOnFail allows deletion of new resources created + during the Helm rollback action when it fails. + type: boolean + disableHooks: + description: DisableHooks prevents hooks from running during the + Helm rollback action. + type: boolean + disableWait: + description: DisableWait disables the waiting for resources to + be ready after a Helm rollback has been performed. + type: boolean + disableWaitForJobs: + description: DisableWaitForJobs disables waiting for jobs to complete + after a Helm rollback has been performed. + type: boolean + force: + description: Force forces resource updates through a replacement + strategy. + type: boolean + recreate: + description: Recreate performs pod restarts for the resource if + applicable. + type: boolean + timeout: + description: Timeout is the time to wait for any individual Kubernetes + operation (like Jobs for hooks) during the performance of a + Helm rollback action. Defaults to 'HelmReleaseSpec.Timeout'. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + type: object + serviceAccountName: + description: The name of the Kubernetes service account to impersonate + when reconciling this HelmRelease. + type: string + storageNamespace: + description: StorageNamespace used for the Helm storage. Defaults + to the namespace of the HelmRelease. + maxLength: 63 + minLength: 1 + type: string + suspend: + description: Suspend tells the controller to suspend reconciliation + for this HelmRelease, it does not apply to already started reconciliations. + Defaults to false. + type: boolean + targetNamespace: + description: TargetNamespace to target when performing operations + for the HelmRelease. Defaults to the namespace of the HelmRelease. + maxLength: 63 + minLength: 1 + type: string + test: + description: Test holds the configuration for Helm test actions for + this HelmRelease. + properties: + enable: + description: Enable enables Helm test actions for this HelmRelease + after an Helm install or upgrade action has been performed. + type: boolean + ignoreFailures: + description: IgnoreFailures tells the controller to skip remediation + when the Helm tests are run but fail. Can be overwritten for + tests run after install or upgrade actions in 'Install.IgnoreTestFailures' + and 'Upgrade.IgnoreTestFailures'. + type: boolean + timeout: + description: Timeout is the time to wait for any individual Kubernetes + operation during the performance of a Helm test action. Defaults + to 'HelmReleaseSpec.Timeout'. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + type: object + timeout: + description: Timeout is the time to wait for any individual Kubernetes + operation (like Jobs for hooks) during the performance of a Helm + action. Defaults to '5m0s'. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + uninstall: + description: Uninstall holds the configuration for Helm uninstall + actions for this HelmRelease. + properties: + deletionPropagation: + default: background + description: DeletionPropagation specifies the deletion propagation + policy when a Helm uninstall is performed. + enum: + - background + - foreground + - orphan + type: string + disableHooks: + description: DisableHooks prevents hooks from running during the + Helm rollback action. + type: boolean + disableWait: + description: DisableWait disables waiting for all the resources + to be deleted after a Helm uninstall is performed. + type: boolean + keepHistory: + description: KeepHistory tells Helm to remove all associated resources + and mark the release as deleted, but retain the release history. + type: boolean + timeout: + description: Timeout is the time to wait for any individual Kubernetes + operation (like Jobs for hooks) during the performance of a + Helm uninstall action. Defaults to 'HelmReleaseSpec.Timeout'. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + type: object + upgrade: + description: Upgrade holds the configuration for Helm upgrade actions + for this HelmRelease. + properties: + cleanupOnFail: + description: CleanupOnFail allows deletion of new resources created + during the Helm upgrade action when it fails. + type: boolean + crds: + description: "CRDs upgrade CRDs from the Helm Chart's crds directory + according to the CRD upgrade policy provided here. Valid values + are `Skip`, `Create` or `CreateReplace`. Default is `Skip` and + if omitted CRDs are neither installed nor upgraded. \n Skip: + do neither install nor replace (update) any CRDs. \n Create: + new CRDs are created, existing CRDs are neither updated nor + deleted. \n CreateReplace: new CRDs are created, existing CRDs + are updated (replaced) but not deleted. \n By default, CRDs + are not applied during Helm upgrade action. With this option + users can opt-in to CRD upgrade, which is not (yet) natively + supported by Helm. https://helm.sh/docs/chart_best_practices/custom_resource_definitions." + enum: + - Skip + - Create + - CreateReplace + type: string + disableHooks: + description: DisableHooks prevents hooks from running during the + Helm upgrade action. + type: boolean + disableOpenAPIValidation: + description: DisableOpenAPIValidation prevents the Helm upgrade + action from validating rendered templates against the Kubernetes + OpenAPI Schema. + type: boolean + disableWait: + description: DisableWait disables the waiting for resources to + be ready after a Helm upgrade has been performed. + type: boolean + disableWaitForJobs: + description: DisableWaitForJobs disables waiting for jobs to complete + after a Helm upgrade has been performed. + type: boolean + force: + description: Force forces resource updates through a replacement + strategy. + type: boolean + preserveValues: + description: PreserveValues will make Helm reuse the last release's + values and merge in overrides from 'Values'. Setting this flag + makes the HelmRelease non-declarative. + type: boolean + remediation: + description: Remediation holds the remediation configuration for + when the Helm upgrade action for the HelmRelease fails. The + default is to not perform any action. + properties: + ignoreTestFailures: + description: IgnoreTestFailures tells the controller to skip + remediation when the Helm tests are run after an upgrade + action but fail. Defaults to 'Test.IgnoreFailures'. + type: boolean + remediateLastFailure: + description: RemediateLastFailure tells the controller to + remediate the last failure, when no retries remain. Defaults + to 'false' unless 'Retries' is greater than 0. + type: boolean + retries: + description: Retries is the number of retries that should + be attempted on failures before bailing. Remediation, using + 'Strategy', is performed between each attempt. Defaults + to '0', a negative integer equals to unlimited retries. + type: integer + strategy: + description: Strategy to use for failure remediation. Defaults + to 'rollback'. + enum: + - rollback + - uninstall + type: string + type: object + timeout: + description: Timeout is the time to wait for any individual Kubernetes + operation (like Jobs for hooks) during the performance of a + Helm upgrade action. Defaults to 'HelmReleaseSpec.Timeout'. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + type: object + values: + description: Values holds the values for this Helm release. + x-kubernetes-preserve-unknown-fields: true + valuesFrom: + description: ValuesFrom holds references to resources containing Helm + values for this HelmRelease, and information about how they should + be merged. + items: + description: ValuesReference contains a reference to a resource + containing Helm values, and optionally the key they can be found + at. + properties: + kind: + description: Kind of the values referent, valid values are ('Secret', + 'ConfigMap'). + enum: + - Secret + - ConfigMap + type: string + name: + description: Name of the values referent. Should reside in the + same namespace as the referring resource. + maxLength: 253 + minLength: 1 + type: string + optional: + description: Optional marks this ValuesReference as optional. + When set, a not found error for the values reference is ignored, + but any ValuesKey, TargetPath or transient error will still + result in a reconciliation failure. + type: boolean + targetPath: + description: TargetPath is the YAML dot notation path the value + should be merged at. When set, the ValuesKey is expected to + be a single flat value. Defaults to 'None', which results + in the values getting merged at the root. + maxLength: 250 + pattern: ^([a-zA-Z0-9_\-.\\\/]|\[[0-9]{1,5}\])+$ + type: string + valuesKey: + description: ValuesKey is the data key where the values.yaml + or a specific value can be found at. Defaults to 'values.yaml'. + When set, must be a valid Data Key, consisting of alphanumeric + characters, '-', '_' or '.'. + maxLength: 253 + pattern: ^[\-._a-zA-Z0-9]+$ + type: string + required: + - kind + - name + type: object + type: array + required: + - chart + - interval + type: object + status: + default: + observedGeneration: -1 + description: HelmReleaseStatus defines the observed state of a HelmRelease. + properties: + conditions: + description: Conditions holds the conditions for the HelmRelease. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + failures: + description: Failures is the reconciliation failure count against + the latest desired state. It is reset after a successful reconciliation. + format: int64 + type: integer + helmChart: + description: HelmChart is the namespaced name of the HelmChart resource + created by the controller for the HelmRelease. + type: string + installFailures: + description: InstallFailures is the install failure count against + the latest desired state. It is reset after a successful reconciliation. + format: int64 + type: integer + lastAppliedRevision: + description: LastAppliedRevision is the revision of the last successfully + applied source. + type: string + lastAttemptedRevision: + description: LastAttemptedRevision is the revision of the last reconciliation + attempt. + type: string + lastAttemptedValuesChecksum: + description: LastAttemptedValuesChecksum is the SHA1 checksum of the + values of the last reconciliation attempt. + type: string + lastHandledReconcileAt: + description: LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value can + be detected. + type: string + lastReleaseRevision: + description: LastReleaseRevision is the revision of the last successful + Helm release. + type: integer + observedGeneration: + description: ObservedGeneration is the last observed generation. + format: int64 + type: integer + upgradeFailures: + description: UpgradeFailures is the upgrade failure count against + the latest desired state. It is reset after a successful reconciliation. + format: int64 + type: integer + type: object + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/component: helm-controller + app.kubernetes.io/instance: flux-system + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: v2.1.2 + name: helm-controller + namespace: flux-system +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/component: helm-controller + app.kubernetes.io/instance: flux-system + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: v2.1.2 + control-plane: controller + name: helm-controller + namespace: flux-system +spec: + replicas: 1 + selector: + matchLabels: + app: helm-controller + template: + metadata: + annotations: + prometheus.io/port: "8080" + prometheus.io/scrape: "true" + labels: + app: helm-controller + spec: + containers: + - args: + - --events-addr=http://notification-controller.flux-system.svc.cluster.local./ + - --watch-all-namespaces=true + - --log-level=info + - --log-encoding=json + - --enable-leader-election + env: + - name: RUNTIME_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + image: ghcr.io/fluxcd/helm-controller:v0.36.2 + imagePullPolicy: IfNotPresent + livenessProbe: + httpGet: + path: /healthz + port: healthz + name: manager + ports: + - containerPort: 8080 + name: http-prom + protocol: TCP + - containerPort: 9440 + name: healthz + protocol: TCP + readinessProbe: + httpGet: + path: /readyz + port: healthz + resources: + limits: + cpu: 1000m + memory: 1Gi + requests: + cpu: 100m + memory: 64Mi + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + volumeMounts: + - mountPath: /tmp + name: temp + nodeSelector: + kubernetes.io/os: linux + priorityClassName: system-cluster-critical + securityContext: + fsGroup: 1337 + serviceAccountName: helm-controller + terminationGracePeriodSeconds: 600 + volumes: + - emptyDir: {} + name: temp +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.0 + labels: + app.kubernetes.io/component: notification-controller + app.kubernetes.io/instance: flux-system + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: v2.1.2 + name: alerts.notification.toolkit.fluxcd.io +spec: + group: notification.toolkit.fluxcd.io + names: + kind: Alert + listKind: AlertList + plural: alerts + singular: alert + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + name: v1beta1 + schema: + openAPIV3Schema: + description: Alert is the Schema for the alerts API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: AlertSpec defines an alerting rule for events involving a + list of objects + properties: + eventSeverity: + default: info + description: Filter events based on severity, defaults to ('info'). + If set to 'info' no events will be filtered. + enum: + - info + - error + type: string + eventSources: + description: Filter events based on the involved objects. + items: + description: CrossNamespaceObjectReference contains enough information + to let you locate the typed referenced object at cluster level + properties: + apiVersion: + description: API version of the referent + type: string + kind: + description: Kind of the referent + enum: + - Bucket + - GitRepository + - Kustomization + - HelmRelease + - HelmChart + - HelmRepository + - ImageRepository + - ImagePolicy + - ImageUpdateAutomation + - OCIRepository + type: string + matchLabels: + additionalProperties: + type: string + description: MatchLabels is a map of {key,value} pairs. A single + {key,value} in the matchLabels map is equivalent to an element + of matchExpressions, whose key field is "key", the operator + is "In", and the values array contains only "value". The requirements + are ANDed. + type: object + name: + description: Name of the referent + maxLength: 53 + minLength: 1 + type: string + namespace: + description: Namespace of the referent + maxLength: 53 + minLength: 1 + type: string + required: + - name + type: object + type: array + exclusionList: + description: A list of Golang regular expressions to be used for excluding + messages. + items: + type: string + type: array + providerRef: + description: Send events using this provider. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + summary: + description: Short description of the impact and affected cluster. + type: string + suspend: + description: This flag tells the controller to suspend subsequent + events dispatching. Defaults to false. + type: boolean + required: + - eventSources + - providerRef + type: object + status: + default: + observedGeneration: -1 + description: AlertStatus defines the observed state of Alert + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + observedGeneration: + description: ObservedGeneration is the last observed generation. + format: int64 + type: integer + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + name: v1beta2 + schema: + openAPIV3Schema: + description: Alert is the Schema for the alerts API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: AlertSpec defines an alerting rule for events involving a + list of objects. + properties: + eventMetadata: + additionalProperties: + type: string + description: EventMetadata is an optional field for adding metadata + to events dispatched by the controller. This can be used for enhancing + the context of the event. If a field would override one already + present on the original event as generated by the emitter, then + the override doesn't happen, i.e. the original value is preserved, + and an info log is printed. + type: object + eventSeverity: + default: info + description: EventSeverity specifies how to filter events based on + severity. If set to 'info' no events will be filtered. + enum: + - info + - error + type: string + eventSources: + description: EventSources specifies how to filter events based on + the involved object kind, name and namespace. + items: + description: CrossNamespaceObjectReference contains enough information + to let you locate the typed referenced object at cluster level + properties: + apiVersion: + description: API version of the referent + type: string + kind: + description: Kind of the referent + enum: + - Bucket + - GitRepository + - Kustomization + - HelmRelease + - HelmChart + - HelmRepository + - ImageRepository + - ImagePolicy + - ImageUpdateAutomation + - OCIRepository + type: string + matchLabels: + additionalProperties: + type: string + description: MatchLabels is a map of {key,value} pairs. A single + {key,value} in the matchLabels map is equivalent to an element + of matchExpressions, whose key field is "key", the operator + is "In", and the values array contains only "value". The requirements + are ANDed. MatchLabels requires the name to be set to `*`. + type: object + name: + description: Name of the referent If multiple resources are + targeted `*` may be set. + maxLength: 53 + minLength: 1 + type: string + namespace: + description: Namespace of the referent + maxLength: 53 + minLength: 1 + type: string + required: + - kind + - name + type: object + type: array + exclusionList: + description: ExclusionList specifies a list of Golang regular expressions + to be used for excluding messages. + items: + type: string + type: array + inclusionList: + description: InclusionList specifies a list of Golang regular expressions + to be used for including messages. + items: + type: string + type: array + providerRef: + description: ProviderRef specifies which Provider this Alert should + use. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + summary: + description: Summary holds a short description of the impact and affected + cluster. + maxLength: 255 + type: string + suspend: + description: Suspend tells the controller to suspend subsequent events + handling for this Alert. + type: boolean + required: + - eventSources + - providerRef + type: object + status: + default: + observedGeneration: -1 + description: AlertStatus defines the observed state of the Alert. + properties: + conditions: + description: Conditions holds the conditions for the Alert. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + lastHandledReconcileAt: + description: LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value can + be detected. + type: string + observedGeneration: + description: ObservedGeneration is the last observed generation. + format: int64 + type: integer + type: object + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.0 + labels: + app.kubernetes.io/component: notification-controller + app.kubernetes.io/instance: flux-system + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: v2.1.2 + name: providers.notification.toolkit.fluxcd.io +spec: + group: notification.toolkit.fluxcd.io + names: + kind: Provider + listKind: ProviderList + plural: providers + singular: provider + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + name: v1beta1 + schema: + openAPIV3Schema: + description: Provider is the Schema for the providers API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: ProviderSpec defines the desired state of Provider + properties: + address: + description: HTTP/S webhook address of this provider + pattern: ^(http|https):// + type: string + certSecretRef: + description: CertSecretRef can be given the name of a secret containing + a PEM-encoded CA certificate (`caFile`) + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + channel: + description: Alert channel for this provider + type: string + proxy: + description: HTTP/S address of the proxy + pattern: ^(http|https):// + type: string + secretRef: + description: Secret reference containing the provider webhook URL + using "address" as data key + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + suspend: + description: This flag tells the controller to suspend subsequent + events handling. Defaults to false. + type: boolean + timeout: + description: Timeout for sending alerts to the provider. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$ + type: string + type: + description: Type of provider + enum: + - slack + - discord + - msteams + - rocket + - generic + - generic-hmac + - github + - gitlab + - bitbucket + - azuredevops + - googlechat + - webex + - sentry + - azureeventhub + - telegram + - lark + - matrix + - opsgenie + - alertmanager + - grafana + - githubdispatch + type: string + username: + description: Bot username for this provider + type: string + required: + - type + type: object + status: + default: + observedGeneration: -1 + description: ProviderStatus defines the observed state of Provider + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + observedGeneration: + description: ObservedGeneration is the last reconciled generation. + format: int64 + type: integer + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + name: v1beta2 + schema: + openAPIV3Schema: + description: Provider is the Schema for the providers API. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: ProviderSpec defines the desired state of the Provider. + properties: + address: + description: Address specifies the endpoint, in a generic sense, to + where alerts are sent. What kind of endpoint depends on the specific + Provider type being used. For the generic Provider, for example, + this is an HTTP/S address. For other Provider types this could be + a project ID or a namespace. + maxLength: 2048 + type: string + certSecretRef: + description: "CertSecretRef specifies the Secret containing a PEM-encoded + CA certificate (in the `ca.crt` key). \n Note: Support for the `caFile` + key has been deprecated." + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + channel: + description: Channel specifies the destination channel where events + should be posted. + maxLength: 2048 + type: string + interval: + description: Interval at which to reconcile the Provider with its + Secret references. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + proxy: + description: Proxy the HTTP/S address of the proxy server. + maxLength: 2048 + pattern: ^(http|https)://.*$ + type: string + secretRef: + description: SecretRef specifies the Secret containing the authentication + credentials for this Provider. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + suspend: + description: Suspend tells the controller to suspend subsequent events + handling for this Provider. + type: boolean + timeout: + description: Timeout for sending alerts to the Provider. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m))+$ + type: string + type: + description: Type specifies which Provider implementation to use. + enum: + - slack + - discord + - msteams + - rocket + - generic + - generic-hmac + - github + - gitlab + - gitea + - bitbucket + - azuredevops + - googlechat + - googlepubsub + - webex + - sentry + - azureeventhub + - telegram + - lark + - matrix + - opsgenie + - alertmanager + - grafana + - githubdispatch + - pagerduty + - datadog + type: string + username: + description: Username specifies the name under which events are posted. + maxLength: 2048 + type: string + required: + - type + type: object + status: + default: + observedGeneration: -1 + description: ProviderStatus defines the observed state of the Provider. + properties: + conditions: + description: Conditions holds the conditions for the Provider. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + lastHandledReconcileAt: + description: LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value can + be detected. + type: string + observedGeneration: + description: ObservedGeneration is the last reconciled generation. + format: int64 + type: integer + type: object + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.12.0 + labels: + app.kubernetes.io/component: notification-controller + app.kubernetes.io/instance: flux-system + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: v2.1.2 + name: receivers.notification.toolkit.fluxcd.io +spec: + group: notification.toolkit.fluxcd.io + names: + kind: Receiver + listKind: ReceiverList + plural: receivers + singular: receiver + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + name: v1 + schema: + openAPIV3Schema: + description: Receiver is the Schema for the receivers API. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: ReceiverSpec defines the desired state of the Receiver. + properties: + events: + description: Events specifies the list of event types to handle, e.g. + 'push' for GitHub or 'Push Hook' for GitLab. + items: + type: string + type: array + interval: + default: 10m + description: Interval at which to reconcile the Receiver with its + Secret references. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + resources: + description: A list of resources to be notified about changes. + items: + description: CrossNamespaceObjectReference contains enough information + to let you locate the typed referenced object at cluster level + properties: + apiVersion: + description: API version of the referent + type: string + kind: + description: Kind of the referent + enum: + - Bucket + - GitRepository + - Kustomization + - HelmRelease + - HelmChart + - HelmRepository + - ImageRepository + - ImagePolicy + - ImageUpdateAutomation + - OCIRepository + type: string + matchLabels: + additionalProperties: + type: string + description: MatchLabels is a map of {key,value} pairs. A single + {key,value} in the matchLabels map is equivalent to an element + of matchExpressions, whose key field is "key", the operator + is "In", and the values array contains only "value". The requirements + are ANDed. MatchLabels requires the name to be set to `*`. + type: object + name: + description: Name of the referent If multiple resources are + targeted `*` may be set. + maxLength: 53 + minLength: 1 + type: string + namespace: + description: Namespace of the referent + maxLength: 53 + minLength: 1 + type: string + required: + - kind + - name + type: object + type: array + secretRef: + description: SecretRef specifies the Secret containing the token used + to validate the payload authenticity. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + suspend: + description: Suspend tells the controller to suspend subsequent events + handling for this receiver. + type: boolean + type: + description: Type of webhook sender, used to determine the validation + procedure and payload deserialization. + enum: + - generic + - generic-hmac + - github + - gitlab + - bitbucket + - harbor + - dockerhub + - quay + - gcr + - nexus + - acr + type: string + required: + - resources + - secretRef + - type + type: object + status: + default: + observedGeneration: -1 + description: ReceiverStatus defines the observed state of the Receiver. + properties: + conditions: + description: Conditions holds the conditions for the Receiver. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + lastHandledReconcileAt: + description: LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value can + be detected. + type: string + observedGeneration: + description: ObservedGeneration is the last observed generation of + the Receiver object. + format: int64 + type: integer + webhookPath: + description: WebhookPath is the generated incoming webhook address + in the format of '/hook/sha256sum(token+name+namespace)'. + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + deprecated: true + deprecationWarning: v1beta1 Receiver is deprecated, upgrade to v1 + name: v1beta1 + schema: + openAPIV3Schema: + description: Receiver is the Schema for the receivers API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: ReceiverSpec defines the desired state of Receiver + properties: + events: + description: A list of events to handle, e.g. 'push' for GitHub or + 'Push Hook' for GitLab. + items: + type: string + type: array + resources: + description: A list of resources to be notified about changes. + items: + description: CrossNamespaceObjectReference contains enough information + to let you locate the typed referenced object at cluster level + properties: + apiVersion: + description: API version of the referent + type: string + kind: + description: Kind of the referent + enum: + - Bucket + - GitRepository + - Kustomization + - HelmRelease + - HelmChart + - HelmRepository + - ImageRepository + - ImagePolicy + - ImageUpdateAutomation + - OCIRepository + type: string + matchLabels: + additionalProperties: + type: string + description: MatchLabels is a map of {key,value} pairs. A single + {key,value} in the matchLabels map is equivalent to an element + of matchExpressions, whose key field is "key", the operator + is "In", and the values array contains only "value". The requirements + are ANDed. + type: object + name: + description: Name of the referent + maxLength: 53 + minLength: 1 + type: string + namespace: + description: Namespace of the referent + maxLength: 53 + minLength: 1 + type: string + required: + - name + type: object + type: array + secretRef: + description: Secret reference containing the token used to validate + the payload authenticity + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + suspend: + description: This flag tells the controller to suspend subsequent + events handling. Defaults to false. + type: boolean + type: + description: Type of webhook sender, used to determine the validation + procedure and payload deserialization. + enum: + - generic + - generic-hmac + - github + - gitlab + - bitbucket + - harbor + - dockerhub + - quay + - gcr + - nexus + - acr + type: string + required: + - resources + - type + type: object + status: + default: + observedGeneration: -1 + description: ReceiverStatus defines the observed state of Receiver + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + observedGeneration: + description: ObservedGeneration is the last observed generation. + format: int64 + type: integer + url: + description: Generated webhook URL in the format of '/hook/sha256sum(token+name+namespace)'. + type: string + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + deprecated: true + deprecationWarning: v1beta2 Receiver is deprecated, upgrade to v1 + name: v1beta2 + schema: + openAPIV3Schema: + description: Receiver is the Schema for the receivers API. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: ReceiverSpec defines the desired state of the Receiver. + properties: + events: + description: Events specifies the list of event types to handle, e.g. + 'push' for GitHub or 'Push Hook' for GitLab. + items: + type: string + type: array + interval: + description: Interval at which to reconcile the Receiver with its + Secret references. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + resources: + description: A list of resources to be notified about changes. + items: + description: CrossNamespaceObjectReference contains enough information + to let you locate the typed referenced object at cluster level + properties: + apiVersion: + description: API version of the referent + type: string + kind: + description: Kind of the referent + enum: + - Bucket + - GitRepository + - Kustomization + - HelmRelease + - HelmChart + - HelmRepository + - ImageRepository + - ImagePolicy + - ImageUpdateAutomation + - OCIRepository + type: string + matchLabels: + additionalProperties: + type: string + description: MatchLabels is a map of {key,value} pairs. A single + {key,value} in the matchLabels map is equivalent to an element + of matchExpressions, whose key field is "key", the operator + is "In", and the values array contains only "value". The requirements + are ANDed. MatchLabels requires the name to be set to `*`. + type: object + name: + description: Name of the referent If multiple resources are + targeted `*` may be set. + maxLength: 53 + minLength: 1 + type: string + namespace: + description: Namespace of the referent + maxLength: 53 + minLength: 1 + type: string + required: + - kind + - name + type: object + type: array + secretRef: + description: SecretRef specifies the Secret containing the token used + to validate the payload authenticity. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + suspend: + description: Suspend tells the controller to suspend subsequent events + handling for this receiver. + type: boolean + type: + description: Type of webhook sender, used to determine the validation + procedure and payload deserialization. + enum: + - generic + - generic-hmac + - github + - gitlab + - bitbucket + - harbor + - dockerhub + - quay + - gcr + - nexus + - acr + type: string + required: + - resources + - type + type: object + status: + default: + observedGeneration: -1 + description: ReceiverStatus defines the observed state of the Receiver. + properties: + conditions: + description: Conditions holds the conditions for the Receiver. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + lastHandledReconcileAt: + description: LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value can + be detected. + type: string + observedGeneration: + description: ObservedGeneration is the last observed generation of + the Receiver object. + format: int64 + type: integer + url: + description: 'URL is the generated incoming webhook address in the + format of ''/hook/sha256sum(token+name+namespace)''. Deprecated: + Replaced by WebhookPath.' + type: string + webhookPath: + description: WebhookPath is the generated incoming webhook address + in the format of '/hook/sha256sum(token+name+namespace)'. + type: string + type: object + type: object + served: true + storage: false + subresources: + status: {} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/component: notification-controller + app.kubernetes.io/instance: flux-system + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: v2.1.2 + name: notification-controller + namespace: flux-system +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/component: notification-controller + app.kubernetes.io/instance: flux-system + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: v2.1.2 + control-plane: controller + name: notification-controller + namespace: flux-system +spec: + ports: + - name: http + port: 80 + protocol: TCP + targetPort: http + selector: + app: notification-controller + type: ClusterIP +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/component: notification-controller + app.kubernetes.io/instance: flux-system + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: v2.1.2 + control-plane: controller + name: webhook-receiver + namespace: flux-system +spec: + ports: + - name: http + port: 80 + protocol: TCP + targetPort: http-webhook + selector: + app: notification-controller + type: ClusterIP +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/component: notification-controller + app.kubernetes.io/instance: flux-system + app.kubernetes.io/part-of: flux + app.kubernetes.io/version: v2.1.2 + control-plane: controller + name: notification-controller + namespace: flux-system +spec: + replicas: 1 + selector: + matchLabels: + app: notification-controller + template: + metadata: + annotations: + prometheus.io/port: "8080" + prometheus.io/scrape: "true" + labels: + app: notification-controller + spec: + containers: + - args: + - --watch-all-namespaces=true + - --log-level=info + - --log-encoding=json + - --enable-leader-election + env: + - name: RUNTIME_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + image: ghcr.io/fluxcd/notification-controller:v1.1.0 + imagePullPolicy: IfNotPresent + livenessProbe: + httpGet: + path: /healthz + port: healthz + name: manager + ports: + - containerPort: 9090 + name: http + protocol: TCP + - containerPort: 9292 + name: http-webhook + protocol: TCP + - containerPort: 8080 + name: http-prom + protocol: TCP + - containerPort: 9440 + name: healthz + protocol: TCP + readinessProbe: + httpGet: + path: /readyz + port: healthz + resources: + limits: + cpu: 1000m + memory: 1Gi + requests: + cpu: 100m + memory: 64Mi + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + volumeMounts: + - mountPath: /tmp + name: temp + nodeSelector: + kubernetes.io/os: linux + securityContext: + fsGroup: 1337 + serviceAccountName: notification-controller + terminationGracePeriodSeconds: 10 + volumes: + - emptyDir: {} + name: temp diff --git a/cluster/flux-system/gotk-sync.yaml b/flux/olympus/base/flux-system/gotk-sync.yaml similarity index 60% rename from cluster/flux-system/gotk-sync.yaml rename to flux/olympus/base/flux-system/gotk-sync.yaml index a9b1c9b4..094efe16 100644 --- a/cluster/flux-system/gotk-sync.yaml +++ b/flux/olympus/base/flux-system/gotk-sync.yaml @@ -1,5 +1,6 @@ +# This manifest was generated by flux. DO NOT EDIT. --- -apiVersion: source.toolkit.fluxcd.io/v1beta1 +apiVersion: source.toolkit.fluxcd.io/v1 kind: GitRepository metadata: name: flux-system @@ -10,16 +11,16 @@ spec: branch: main secretRef: name: flux-system - url: ssh://git@git.xirion.net:2222/olympus/flux.git + url: ssh://gitea@git.0x76.dev:42/v/infrastructure.git --- -apiVersion: kustomize.toolkit.fluxcd.io/v1beta2 +apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: flux-system namespace: flux-system spec: interval: 10m0s - path: ./cluster + path: ./flux/olympus/base prune: true sourceRef: kind: GitRepository diff --git a/flux/olympus/base/flux-system/kustomization.yaml b/flux/olympus/base/flux-system/kustomization.yaml new file mode 100644 index 00000000..42cac648 --- /dev/null +++ b/flux/olympus/base/flux-system/kustomization.yaml @@ -0,0 +1,6 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - gotk-components.yaml + - gotk-sync.yaml + - repositories diff --git a/flux/olympus/base/flux-system/repositories/helm/external-secrets.yaml b/flux/olympus/base/flux-system/repositories/helm/external-secrets.yaml new file mode 100644 index 00000000..a68409ba --- /dev/null +++ b/flux/olympus/base/flux-system/repositories/helm/external-secrets.yaml @@ -0,0 +1,8 @@ +apiVersion: source.toolkit.fluxcd.io/v1beta2 +kind: HelmRepository +metadata: + name: external-secrets + namespace: flux-system +spec: + interval: 1h + url: https://charts.external-secrets.io diff --git a/flux/olympus/base/flux-system/repositories/helm/kustomization.yaml b/flux/olympus/base/flux-system/repositories/helm/kustomization.yaml new file mode 100644 index 00000000..9e58514b --- /dev/null +++ b/flux/olympus/base/flux-system/repositories/helm/kustomization.yaml @@ -0,0 +1,5 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - external-secrets.yaml + diff --git a/flux/olympus/base/flux-system/repositories/kustomization.yaml b/flux/olympus/base/flux-system/repositories/kustomization.yaml new file mode 100644 index 00000000..dadf6d60 --- /dev/null +++ b/flux/olympus/base/flux-system/repositories/kustomization.yaml @@ -0,0 +1,5 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - helm + diff --git a/flux/olympus/core/external-secrets/.gitignore b/flux/olympus/core/external-secrets/.gitignore new file mode 100644 index 00000000..5eec00f7 --- /dev/null +++ b/flux/olympus/core/external-secrets/.gitignore @@ -0,0 +1 @@ +vault-secret-id.yaml \ No newline at end of file diff --git a/flux/olympus/core/external-secrets/helm-release.yaml b/flux/olympus/core/external-secrets/helm-release.yaml new file mode 100644 index 00000000..7ca3ee27 --- /dev/null +++ b/flux/olympus/core/external-secrets/helm-release.yaml @@ -0,0 +1,29 @@ +--- +apiVersion: helm.toolkit.fluxcd.io/v2beta1 +kind: HelmRelease +metadata: + name: external-secrets + namespace: security +spec: + interval: 30m + chart: + spec: + chart: external-secrets + version: 0.9.9 + interval: 30m + sourceRef: + kind: HelmRepository + name: external-secrets + namespace: flux-system + values: + installCRDs: true + replicaCount: 1 + leaderElect: true + # serviceMonitor: + # enabled: true + # webhook: + # serviceMonitor: + # enabled: true + # certController: + # serviceMonitor: + # enabled: true diff --git a/flux/olympus/core/external-secrets/kustomization.yaml b/flux/olympus/core/external-secrets/kustomization.yaml new file mode 100644 index 00000000..04c4cf13 --- /dev/null +++ b/flux/olympus/core/external-secrets/kustomization.yaml @@ -0,0 +1,5 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - helm-release.yaml + - vault-secret-store.yaml diff --git a/flux/olympus/core/external-secrets/vault-secret-id.example.yaml b/flux/olympus/core/external-secrets/vault-secret-id.example.yaml new file mode 100644 index 00000000..e9c57519 --- /dev/null +++ b/flux/olympus/core/external-secrets/vault-secret-id.example.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: Secret +metadata: + name: vault-secret-id + namespace: security +data: + secret-id: XXXXXX # Obtain by `vault write -f auth/approle/role/external-secrets/secret-id` diff --git a/flux/olympus/core/external-secrets/vault-secret-store.yaml b/flux/olympus/core/external-secrets/vault-secret-store.yaml new file mode 100644 index 00000000..f09f88f0 --- /dev/null +++ b/flux/olympus/core/external-secrets/vault-secret-store.yaml @@ -0,0 +1,27 @@ +apiVersion: external-secrets.io/v1beta1 +kind: ClusterSecretStore +metadata: + name: vault + namespace: security +spec: + provider: + vault: + server: "http://vault.olympus:8200" + path: "k8s" + version: "v2" + auth: + # VaultAppRole authenticates with Vault using the + # App Role auth mechanism + # https://www.vaultproject.io/docs/auth/approle + appRole: + # Path where the App Role authentication backend is mounted + path: "approle" + # RoleID configured in the App Role authentication backend + # `vault read auth/approle/role/external-secrets/role-id` + roleId: "bb841a0e-45c1-9dab-36f0-f72647d6aff0" + # Reference to a key in a K8 Secret that contains the App Role SecretId + # (not commited in git) + secretRef: + name: "vault-secret-id" + namespace: "security" + key: "secret-id" diff --git a/flux/olympus/core/kustomization.yaml b/flux/olympus/core/kustomization.yaml new file mode 100644 index 00000000..1611c859 --- /dev/null +++ b/flux/olympus/core/kustomization.yaml @@ -0,0 +1,5 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - namespaces + - external-secrets diff --git a/flux/olympus/core/namespaces/kustomization.yaml b/flux/olympus/core/namespaces/kustomization.yaml new file mode 100644 index 00000000..be604cf1 --- /dev/null +++ b/flux/olympus/core/namespaces/kustomization.yaml @@ -0,0 +1,6 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - websites.yaml + - security.yaml + - services.yaml diff --git a/flux/olympus/core/namespaces/security.yaml b/flux/olympus/core/namespaces/security.yaml new file mode 100644 index 00000000..65f1a838 --- /dev/null +++ b/flux/olympus/core/namespaces/security.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: security diff --git a/flux/olympus/core/namespaces/services.yaml b/flux/olympus/core/namespaces/services.yaml new file mode 100644 index 00000000..da390d0d --- /dev/null +++ b/flux/olympus/core/namespaces/services.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: services diff --git a/flux/olympus/core/namespaces/websites.yaml b/flux/olympus/core/namespaces/websites.yaml new file mode 100644 index 00000000..9b4e8bc3 --- /dev/null +++ b/flux/olympus/core/namespaces/websites.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: websites diff --git a/nixos/common/default.nix b/nixos/common/default.nix new file mode 100644 index 00000000..03d5d45c --- /dev/null +++ b/nixos/common/default.nix @@ -0,0 +1,106 @@ +{ lib, pkgs, inputs, config, ... }: { + imports = + [ ./users ./modules inputs.vault-secrets.nixosModules.vault-secrets ]; + + vault-secrets = + let + inherit (config.networking) domain hostName; + server = if domain == "olympus" then "vault" else "vault-0"; + in + lib.mkIf (domain == "olympus" || domain == "hades") { + vaultPrefix = "${domain}_secrets/nixos"; + vaultAddress = "http://${server}.${domain}:8200/"; + approlePrefix = "${domain}-${hostName}"; + }; + + home-manager = { + useGlobalPkgs = true; + useUserPackages = true; + extraSpecialArgs = { inherit inputs; }; + sharedModules = [ ./hm-modules inputs.nixvim.homeManagerModules.nixvim ]; + }; + + # Clean /tmp on boot. + boot.tmp.cleanOnBoot = true; + + # Set your time zone. + time.timeZone = lib.mkDefault "Europe/Amsterdam"; + + # Systemd OOMd + # Fedora enables these options by default. See the 10-oomd-* files here: + # https://src.fedoraproject.org/rpms/systemd/tree/acb90c49c42276b06375a66c73673ac3510255 + systemd.oomd = { + enableRootSlice = true; + enableUserServices = true; + }; + + # Nix Settings + nix = { + registry.nixpkgs.flake = inputs.nixpkgs; + nixPath = [ "nixpkgs=${inputs.nixpkgs}" ]; + package = pkgs.nixUnstable; + settings = { + auto-optimise-store = true; + trusted-users = [ "root" "vivian" ]; + substituters = [ + "https://nix-community.cachix.org" + "https://nixpkgs-review-bot.cachix.org" + "https://colmena.cachix.org" + "https://cache.garnix.io" + "https://cachix.cachix.org" + ]; + trusted-public-keys = [ + "cachix.cachix.org-1:eWNHQldwUO7G2VkjpnjDbWwy4KQ/HNxht7H4SSoMckM=" + "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" + "nixpkgs-review-bot.cachix.org-1:eppgiDjPk7Hkzzz7XlUesk3rcEHqNDozGOrcLc8IqwE=" + "colmena.cachix.org-1:7BzpDnjjH8ki2CT3f6GdOk7QAzPOl+1t3LvTLXqYcSg=" + "cache.garnix.io:CTFPyKSLcx5RMJKfLo5EEPUObbA78b0YQ2DTCJXqr9g=" + ]; + }; + optimise = { + automatic = true; + dates = [ "weekly" ]; + }; + gc = { + automatic = true; + dates = "weekly"; + randomizedDelaySec = "3h"; + options = "--delete-older-than 7d"; + }; + extraOptions = '' + experimental-features = nix-command flakes + ''; + }; + + nixpkgs.config.allowUnfree = true; + + nixpkgs.config.permittedInsecurePackages = + [ "nodejs-16.20.2" "nodejs-14.21.3" "openssl-1.1.1w" ]; + + # Limit the systemd journal to 100 MB of disk or the + # last 7 days of logs, whichever happens first. + services.journald.extraConfig = '' + SystemMaxUse=100M + MaxFileSec=7day + ''; + + # Enable SSH + services.openssh = { + enable = true; + settings = { + PasswordAuthentication = lib.mkDefault false; + PermitRootLogin = lib.mkDefault "no"; + }; + }; + + # Debloat + documentation = { + enable = lib.mkForce false; + doc.enable = lib.mkForce false; + man.enable = lib.mkForce false; + info.enable = lib.mkForce false; + nixos.enable = lib.mkForce false; + }; + + system.disableInstallerTools = lib.mkDefault true; +} diff --git a/nixos/common/desktop/README.md b/nixos/common/desktop/README.md new file mode 100644 index 00000000..32380744 --- /dev/null +++ b/nixos/common/desktop/README.md @@ -0,0 +1,9 @@ +# Common Desktop Config +This is where I store the NixOS config that is common between +my laptop and desktop + +## Files +* `./default.nix`: Contains common systemwide configuration + * See also my NixOS [modules](../modules), specifically gnome +* `./home.nix`: Contains common user-level configuration + * See also my Home-Manager [modules](../hm-modules) diff --git a/nixos/common/desktop/default.nix b/nixos/common/desktop/default.nix new file mode 100644 index 00000000..c7201b15 --- /dev/null +++ b/nixos/common/desktop/default.nix @@ -0,0 +1,114 @@ +{ pkgs, lib, inputs, ... }: { + # Bootloader. + boot = { + kernelPackages = lib.mkDefault pkgs.linuxPackages_latest; + loader = { + systemd-boot.enable = lib.mkDefault true; + efi.canTouchEfiVariables = true; + efi.efiSysMountPoint = "/boot/efi"; + }; + kernel.sysctl = { "fs.inotify.max_user_watches" = 524288; }; + initrd = { + systemd.enable = true; + verbose = false; + }; + }; + + hardware.keyboard.qmk.enable = true; + home-manager = { + useGlobalPkgs = true; + useUserPackages = true; + users.vivian = import ./home.nix; + extraSpecialArgs = { inherit inputs; }; + }; + services = { + + # Enable my config for the gnome desktop environment + v.gnome.enable = true; + + # Enable CUPS to print documents. + printing.enable = true; + pipewire = { + enable = true; + alsa.enable = true; + alsa.support32Bit = true; + pulse.enable = true; + # If you want to use JACK applications, uncomment this + #jack.enable = true; + + # use the example session manager (no others are packaged yet so this is enabled by default, + # no need to redefine it in your config for now) + #media-session.enable = true; + }; + }; + + # Set your time zone. + time.timeZone = "Europe/Amsterdam"; + + # Select internationalisation properties. + i18n.defaultLocale = "en_GB.UTF-8"; + i18n.extraLocaleSettings = { + LC_ADDRESS = "nl_NL.UTF-8"; + LC_IDENTIFICATION = "nl_NL.UTF-8"; + LC_MEASUREMENT = "nl_NL.UTF-8"; + LC_MONETARY = "nl_NL.UTF-8"; + LC_NAME = "nl_NL.UTF-8"; + LC_NUMERIC = "nl_NL.UTF-8"; + LC_PAPER = "nl_NL.UTF-8"; + LC_TELEPHONE = "nl_NL.UTF-8"; + LC_TIME = "nl_NL.UTF-8"; + }; + + # Global Packages + environment.systemPackages = with pkgs; [ wireguard-tools sbctl podman-compose ]; + + # programs.virt-manager = { + # enable = true; + # }; + + # Enable sound with pipewire. + sound.enable = true; + hardware.pulseaudio.enable = false; + security.rtkit.enable = true; + + virtualisation = { + podman.enable = true; + libvirtd = { + enable = true; + qemu.package = pkgs.qemu_kvm; + }; + }; + + fonts.packages = with pkgs; [ + material-design-icons + noto-fonts + noto-fonts-cjk + noto-fonts-emoji + dejavu_fonts + (nerdfonts.override { + fonts = + [ "DejaVuSansMono" "Ubuntu" "DroidSansMono" "NerdFontsSymbolsOnly" ]; + }) + ]; + programs = { + steam = { + + enable = true; + # Open ports in the firewall for Steam Remote Play + remotePlay.openFirewall = true; + package = pkgs.steam.override { + extraPkgs = pkgs: with pkgs; [ gamescope mangohud ]; + }; + }; + + gamemode.enable = true; + + adb.enable = true; + }; + networking = { + # Networking + networkmanager.enable = true; + firewall.checkReversePath = false; + firewall.enable = false; + }; +} diff --git a/nixos/common/desktop/home.nix b/nixos/common/desktop/home.nix new file mode 100644 index 00000000..033f235b --- /dev/null +++ b/nixos/common/desktop/home.nix @@ -0,0 +1,95 @@ +{ pkgs, inputs, config, ... }: +let + tex = pkgs.texlive.combine { + inherit (pkgs.texlive) scheme-full; + dnd-5e-latex-template = { pkgs = [ pkgs.v.dnd-5e-latex-template ]; }; + }; + my-python-packages = ps: with ps; [ pandas requests numpy ]; +in { + home.packages = with pkgs; [ + (python3.withPackages my-python-packages) + btop + calibre + celluloid + cinny-desktop + element-desktop-wayland + fusee-launcher + fractal-next + gcc + gimp + helix + inputs.attic.packages.${pkgs.system}.attic + inputs.comma.packages.${pkgs.system}.default + inputs.webcord.packages.${pkgs.system}.default + jetbrains.clion + jetbrains.rust-rover + kdenlive + libreoffice-fresh + mattermost-desktop + mullvad-vpn + neofetch + nixfmt + nixpkgs-review + plex-media-player + plexamp + spotify + qmk + solo2-cli + tex + unzip + yt-dlp + ]; + + # Enable my own hm modules + themes.v.catppuccin.enable = true; + programs = { + v = { + vscode.enable = true; + nvim.enable = true; + rust.enable = true; + }; + + riff = { + enable = true; + direnv = true; + }; + + firefox.enable = true; + + chromium = { + enable = true; + package = pkgs.ungoogled-chromium; + }; + + direnv = { + enable = true; + nix-direnv.enable = true; + }; + + zsh = { + enable = true; + sessionVariables = { DIRENV_LOG_FORMAT = ""; }; + }; + + thunderbird = { + enable = true; + profiles.default = { isDefault = true; }; + }; + }; + + # Syncthing + services.syncthing.enable = true; + xdg.userDirs = let home = config.home.homeDirectory; + in { + enable = true; + createDirectories = true; + desktop = "${home}/.desktop"; + documents = "${home}/cloud/Documents"; + download = "${home}/dl"; + music = "${home}/cloud/Music"; + pictures = "${home}/cloud/Pictures"; + publicShare = "${home}/.publicShare"; + templates = "${home}/.templates"; + videos = "${home}/cloud/Videos"; + }; +} diff --git a/nixos/common/generic-lxc.nix b/nixos/common/generic-lxc.nix new file mode 100644 index 00000000..98749442 --- /dev/null +++ b/nixos/common/generic-lxc.nix @@ -0,0 +1,13 @@ +_: { + # See also: https://blog.xirion.net/posts/nixos-proxmox-lxc/ + + # Supress systemd services that don't work (correctly) on LXC + systemd.suppressedSystemUnits = [ + "dev-mqueue.mount" + "sys-kernel-debug.mount" + "sys-fs-fuse-connections.mount" + ]; + + # https://github.com/NixOS/nixpkgs/issues/157449#issuecomment-1459299764 + boot.specialFileSystems."/run".options = [ "rshared" ]; +} diff --git a/nixos/common/generic-vm.nix b/nixos/common/generic-vm.nix new file mode 100644 index 00000000..086bf638 --- /dev/null +++ b/nixos/common/generic-vm.nix @@ -0,0 +1,6 @@ +_: { + networking.useDHCP = true; + + # Enable qemu guest agent + services.qemuGuest.enable = true; +} diff --git a/nixos/common/hm-modules/catppuccin.nix b/nixos/common/hm-modules/catppuccin.nix new file mode 100644 index 00000000..68c7191e --- /dev/null +++ b/nixos/common/hm-modules/catppuccin.nix @@ -0,0 +1,40 @@ +{ config, pkgs, lib, ... }: +with lib; +let cfg = config.themes.v.catppuccin; +in { + options.themes.v.catppuccin = { enable = mkEnableOption "catppuccin"; }; + config = + let + theme = "Catppuccin-Pink-Dark"; + cursorTheme = config.home.pointerCursor.name; + in + mkIf cfg.enable { + home.pointerCursor = { + name = "Bibata_Ghost"; + size = 24; + package = pkgs.bibata-cursors-translucent; + }; + + gtk = { + enable = true; + theme = { + name = theme; + package = pkgs.catppuccin-gtk; + }; + iconTheme = { + name = "Papirus-Dark"; + package = pkgs.papirus-icon-theme.override { color = "violet"; }; + }; + cursorTheme = { + name = cursorTheme; + inherit (config.home.pointerCursor) package size; + }; + }; + + programs.vscode = { + userSettings."workbench.colorTheme" = "Catppuccin Frappé"; + extensions = [ pkgs.vscode-extensions.catppuccin.catppuccin-vsc ]; + }; + }; +} + diff --git a/nixos/common/hm-modules/default.nix b/nixos/common/hm-modules/default.nix new file mode 100644 index 00000000..2dbbe8f1 --- /dev/null +++ b/nixos/common/hm-modules/default.nix @@ -0,0 +1,3 @@ +{ ... }: { + imports = [ ./catppuccin.nix ./nvim.nix ./riff.nix ./vscode.nix ./git.nix ./rust.nix ]; +} diff --git a/nixos/common/hm-modules/git.nix b/nixos/common/hm-modules/git.nix new file mode 100644 index 00000000..af8d83cf --- /dev/null +++ b/nixos/common/hm-modules/git.nix @@ -0,0 +1,31 @@ +{ config, pkgs, lib, ... }: +with lib; +let cfg = config.programs.v.git; +in { + options.programs.v.git = { enable = mkEnableOption "git"; }; + config = mkIf cfg.enable { + programs.git = { + enable = true; + package = pkgs.gitAndTools.gitFull; + userName = "0x76"; + userEmail = "v@0x76.dev"; + lfs.enable = true; + extraConfig = { + push.autoSetupRemote = true; + init.defaultBranch = "main"; + # Git merge driver that always grabs upstream changes + # Useful for e.g. lock files + merge.ours = { + name = "Overwrite Upstream Changes"; + driver = "cp -f '%A' '%B'"; + }; + }; + + difftastic.enable = true; + }; + + home.file.".config/git/attributes".text = '' + flake.lock merge=ours + ''; + }; +} diff --git a/nixos/common/hm-modules/nvim.nix b/nixos/common/hm-modules/nvim.nix new file mode 100644 index 00000000..2accf6a0 --- /dev/null +++ b/nixos/common/hm-modules/nvim.nix @@ -0,0 +1,158 @@ +{ config, pkgs, lib, ... }: +with lib; +let cfg = config.programs.v.nvim; +in { + options.programs.v.nvim = { enable = mkEnableOption "nvim"; }; + config = mkIf cfg.enable { + programs.nixvim = { + enable = true; + package = pkgs.neovim-unwrapped; + vimAlias = true; + + globals.mapleader = " "; + + options.number = true; + + keymaps = [ + { + mode = "n"; + key = "ff"; + action = "require('telescope.builtin').find_files"; + lua = true; + } + { + mode = "n"; + key = "fg"; + action = "require('telescope.builtin').live_grep"; + lua = true; + } + { + mode = "n"; + key = ""; + action = "require('Comment.api').toggle.linewise.current"; + lua = true; + } + { + mode = "n"; + key = "g="; + action = "vim.lsp.buf.format"; + lua = true; + } + ]; + + # keymaps = [ + # { + # key = "ff"; + # mode = "n"; + # lua = true; + # action = "require('telescope.builtin').find_files()"; + # } + # { + # key = "fg"; + # mode = "n"; + # lua = true; + # action = "require('Comment.api').toggle.linewise.current()"; + # } + # { + # key = "g="; + # mode = "n"; + # lua = true; + # action = "vim.lsp.buf.format{async=true}"; + # } + # ]; + + extraPlugins = with pkgs.vimPlugins; [ catppuccin-nvim luasnip ]; + + colorscheme = "catppuccin-frappe"; + + extraConfigLua = ""; + + plugins = { + bufferline.enable = true; + none-ls = { + enable = true; + sources = { + formatting.nixpkgs_fmt.enable = true; + code_actions.shellcheck.enable = true; + code_actions.statix.enable = true; + diagnostics = { + statix.enable = true; + deadnix.enable = true; + shellcheck.enable = true; + }; + }; + }; + nix.enable = true; + treesitter = { + enable = true; + nixGrammars = true; + # ensureInstalled = [ ]; + }; + surround.enable = true; + fugitive.enable = true; + gitgutter.enable = true; + lualine = { + enable = true; + theme = "catppuccin"; + }; + telescope = { + enable = true; + extensions.fzf-native.enable = true; + extensions.fzf-native.fuzzy = true; + }; + comment-nvim = { enable = true; }; + lsp = { + enable = true; + servers = { + nil_ls.enable = true; + rust-analyzer.enable = true; + pyright.enable = true; + elixirls.enable = true; + clangd.enable = true; + yamlls.enable = true; + }; + }; + trouble.enable = true; + lspkind.enable = true; + nvim-cmp = { + enable = true; + autoEnableSources = true; + sources = [ + { name = "nvim_lsp"; } + { name = "cmp-latex-symbols"; } + { + name = "luasnip"; + option = { show_autosnippets = true; }; + } + { name = "cmp-spell"; } + { name = "cmp-rg"; } + { name = "path"; } + { name = "buffer"; } + ]; + snippet.expand = "luasnip"; + mappingPresets = [ "insert" "cmdline" ]; + mapping = { + "" = "cmp.mapping.confirm({ select = true })"; + "" = { + modes = [ "i" "s" ]; + action = '' + function(fallback) + local luasnip = require('luasnip') + if cmp.visible() then + cmp.select_next_item() + elseif luasnip.expandable() then + luasnip.expand() + elseif luasnip.expand_or_jumpable() then + luasnip.expand_or_jump() + else + fallback() + end + end + ''; + }; + }; + }; + }; + }; + }; +} diff --git a/nixos/common/hm-modules/riff.nix b/nixos/common/hm-modules/riff.nix new file mode 100644 index 00000000..509a782d --- /dev/null +++ b/nixos/common/hm-modules/riff.nix @@ -0,0 +1,28 @@ +{ config, pkgs, lib, inputs, ... }: +with lib; +let cfg = config.programs.riff; +in { + options.programs.riff = { + enable = mkEnableOption "riff"; + direnv = mkOption { + type = types.bool; + default = false; + description = '' + Whether to enable direnv support + ''; + }; + }; + config = mkIf cfg.enable { + home.packages = [ inputs.riff.packages.${pkgs.system}.riff ]; + + xdg.configFile."direnv/lib/riff.sh" = mkIf cfg.direnv { + executable = true; + text = '' + use_riff() { + watch_file Cargo.toml watch_file Cargo.lock + eval "$(riff --offline print-dev-env)" + } + ''; + }; + }; +} diff --git a/nixos/common/hm-modules/rust.nix b/nixos/common/hm-modules/rust.nix new file mode 100644 index 00000000..752ed047 --- /dev/null +++ b/nixos/common/hm-modules/rust.nix @@ -0,0 +1,23 @@ +{ pkgs, lib, config, ... }: +with lib; +let cfg = config.programs.v.rust; +in { + options.programs.v.rust = { enable = mkEnableOption "rust"; }; + config = mkIf cfg.enable { + home = { + packages = with pkgs; [ rustup ]; + + file = { + ".cargo/config.toml".text = '' + [registries.crates-io] + protocol = "sparse" + + [build] + rustc-wrapper = "${pkgs.sccache}/bin/sccache" + ''; + }; + + sessionPath = [ "$HOME/.cargo/bin" ]; + }; + }; +} diff --git a/nixos/common/hm-modules/vscode.nix b/nixos/common/hm-modules/vscode.nix new file mode 100644 index 00000000..8a3ce1b5 --- /dev/null +++ b/nixos/common/hm-modules/vscode.nix @@ -0,0 +1,72 @@ +{ config, pkgs, lib, ... }: +with lib; +let cfg = config.programs.v.vscode; +in { + options.programs.v.vscode = { enable = mkEnableOption "vscode"; }; + config = mkIf cfg.enable { + programs.vscode = { + enable = true; + package = pkgs.vscode; + userSettings = { + "ltex.language" = "en-GB"; + "latex-workshop.linting.chktex.enabled" = true; + "latex-workshop.latex.clean.subfolder.enabled" = true; + "latex-workshop.latex.outDir" = "%TMPDIR%/%RELATIVE_DOC%"; + "editor.fontFamily" = + "'DejaVuSansMono Nerd Font', 'monospace', monospace"; + "keyboard.dispatch" = "keyCode"; + "rust-analyzer.server.path" = "${pkgs.rust-analyzer}/bin/rust-analyzer"; + "terminal.integrated.defaultProfile.linux" = "zsh"; + "nix.enableLanguageServer" = true; # Enable LSP. + "nix.serverPath" = "${pkgs.nil}/bin/nil"; + "[nix]" = { "editor.defaultFormatter" = "brettm12345.nixfmt-vscode"; }; + "[python]" = { "editor.formatOnType" = true; }; + "rust-analyzer.checkOnSave.command" = "clippy"; + "debug.allowBreakpointsEverywhere" = true; + "C_Cpp.clang_format_fallbackStyle" = "{ BasedOnStyle: Google, IndentWidth: 4, ColumnLimit: 0}"; + # Don't index unecessary things + "files.exclude" = { + "**/.vscode" = true; + "**/.git" = true; + "**/.svn" = true; + "**/.hg" = true; + "**/.deps" = true; + "**/CVS" = true; + "**/.DS_Store" = true; + "/bin" = true; + "/boot" = true; + "/cdrom" = true; + "/dev" = true; + "/proc" = true; + "/etc" = true; + "/nix" = true; + }; + }; + extensions = with pkgs.vscode-extensions; + with pkgs.v.vscode-extensions; [ + brettm12345.nixfmt-vscode + codezombiech.gitignore + editorconfig.editorconfig + foxundermoon.shell-format + james-yu.latex-workshop + jnoortheen.nix-ide + matklad.rust-analyzer + mkhl.direnv + ms-vscode-remote.remote-ssh + ms-vscode.cpptools + platformio.platformio-ide + redhat.vscode-yaml + redhat.vscode-xml + tamasfe.even-better-toml + valentjn.vscode-ltex + vscodevim.vim + vadimcn.vscode-lldb + xaver.clang-format + sumneko.lua + davidlday.languagetool-linter + ]; + }; + + }; +} + diff --git a/nixos/common/modules/default.nix b/nixos/common/modules/default.nix new file mode 100644 index 00000000..66727027 --- /dev/null +++ b/nixos/common/modules/default.nix @@ -0,0 +1,3 @@ +{ ... }: { + imports = [ ./meta.nix ./nginx.nix ./dns.nix ./flood.nix ./gnome ./unpackerr.nix ./vault.nix ]; +} diff --git a/nixos/common/modules/dns.nix b/nixos/common/modules/dns.nix new file mode 100644 index 00000000..0b9ed85e --- /dev/null +++ b/nixos/common/modules/dns.nix @@ -0,0 +1,110 @@ +{ config, pkgs, lib, hosts, flat_hosts, ... }: +# DNS Module to set up Unbound DNS with all my hosts in the config +# Used for DNS Servers and my laptop +with lib; +let + inherit (builtins) filter hasAttr attrNames; + domains = attrNames hosts; + ipv4Host = filter (hasAttr "ip") flat_hosts; + ipv6Hosts = filter (hasAttr "ip6") flat_hosts; + + localData = { hostname, realm, ip, ... }: ''"${hostname}.${realm}. A ${ip}"''; + local6Data = { hostname, realm, ip6, ... }: + ''"${hostname}.${realm}. AAAA ${ip6}"''; + ptrData = { hostname, realm, ip, ... }: ''"${ip} ${hostname}.${realm}"''; + ptr6Data = { hostname, realm, ip6, ... }: ''"${ip6} ${hostname}.${realm}"''; + + cfg = config.services.v.dns; +in +{ + options.services.v.dns = { + enable = mkEnableOption "v.dns"; + + openFirewall = mkOption { + type = types.bool; + default = false; + description = lib.mdDoc '' + Whether to open port 53 in the firwall for unbound dns + And `services.prometheus.exporters.unbound.port` for metrics (if enabled). + ''; + }; + + enableMetrics = mkOption { + type = types.bool; + default = cfg.mode == "server"; + description = '' + Enable prometheus metrics + ''; + }; + + mode = mkOption { + type = types.strMatching "^(server|laptop)$"; + default = "laptop"; + description = '' + Whether to configure the DNS in server mode (listen on all interfaces) or laptop mode (just on localhost) + ''; + }; + }; + + config = mkIf cfg.enable { + networking.firewall = mkIf cfg.openFirewall { + allowedTCPPorts = [ 53 ]; + allowedUDPPorts = [ 53 ]; + }; + services.prometheus.exporters.unbound = mkIf cfg.enableMetrics { + enable = true; + inherit (cfg) openFirewall; + inherit (config.services.unbound) group; + controlInterface = config.services.unbound.localControlSocketPath; + }; + services.unbound = { + enable = true; + package = pkgs.v.unbound; + localControlSocketPath = mkIf cfg.enableMetrics "/run/unbound/unbound.socket"; + settings = { + server = mkMerge [ + { + use-syslog = "yes"; + module-config = ''"validator iterator"''; + + local-zone = + map (localdomain: ''"${localdomain}}." transparent'') domains; + local-data = (map localData ipv4Host) ++ (map local6Data ipv6Hosts); + local-data-ptr = (map ptrData ipv4Host) ++ (map ptr6Data ipv6Hosts); + + private-address = [ + "127.0.0.0/8" + "10.0.0.0/8" + "::ffff:a00:0/104" + "172.16.0.0/12" + "::ffff:ac10:0/108" + "169.254.0.0/16" + "::ffff:a9fe:0/112" + "192.168.0.0/16" + "::ffff:c0a8:0/112" + "fd00::/8" + "fe80::/10" + ]; + } + (mkIf (cfg.mode == "server") { + interface-automatic = "yes"; + interface = [ "0.0.0.0" "::0" ]; + access-control = [ + "127.0.0.1/32 allow_snoop" + "::1 allow_snoop" + "10.42.0.0/16 allow" + "127.0.0.0/8 allow" + "192.168.0.0/23 allow" + "192.168.2.0/24 allow" + "::1/128 allow" + ]; + }) + (mkIf (cfg.mode == "laptop") { + interface = [ "127.0.0.1" "::1" ]; + access-control = [ "127.0.0.1/32 allow_snoop" "::1 allow_snoop" ]; + }) + ]; + }; + }; + }; +} diff --git a/nixos/common/modules/flood.nix b/nixos/common/modules/flood.nix new file mode 100644 index 00000000..64c20b33 --- /dev/null +++ b/nixos/common/modules/flood.nix @@ -0,0 +1,153 @@ +{ config, pkgs, lib, ... }: +with lib; +let cfg = config.services.flood; +in { + options.services.flood = { + enable = mkEnableOption "flood"; + + user = mkOption { + default = "flood"; + type = types.str; + description = '' + User account under which flood runs. + ''; + }; + + group = mkOption { + type = types.str; + default = "rtorrent"; + description = '' + Group under which flood runs. + Flood needs to have the correct permissions if accessing rtorrent through the socket. + ''; + }; + + package = mkOption { + type = types.package; + default = pkgs.flood; + defaultText = "pkgs.flood"; + description = '' + The flood package to use. + ''; + }; + + host = mkOption { + type = types.str; + default = "127.0.0.1"; + description = '' + Address flood binds to. + ''; + }; + + port = mkOption { + type = types.port; + default = 3000; + description = '' + The flood web port. + ''; + }; + + openFirewall = mkOption { + type = types.bool; + default = false; + description = '' + Whether to open the firewall for the port in . + ''; + }; + + rpcSocket = mkOption { + type = types.str; + readOnly = true; + default = "/run/rtorrent/rpc.sock"; + description = '' + RPC socket path. + (Only used when auth=none). + ''; + }; + + dataDir = mkOption { + type = types.str; + default = "/var/lib/flood"; + description = '' + The directory where flood stores its data files. + ''; + }; + + downloadDir = mkOption { + type = types.str; + default = "/var/lib/rtorrent/download"; + description = '' + Root directory for downloaded files. + ''; + }; + + authMode = mkOption { + type = types.str; + default = "none"; + description = '' + Access control and user management method. + Either 'default' or 'none'. + ''; + }; + + ssl = mkOption { + type = types.bool; + default = false; + description = '' + Enable SSL. + key.pem and fullchain.pem needed in runtime directory. + ''; + }; + + baseURI = mkOption { + type = types.str; + default = "/"; + description = '' + This URI will prefix all of Flood's HTTP requests + ''; + }; + }; + + config = mkIf cfg.enable { + # Create group if set to default + users.groups = mkIf (cfg.group == "rtorrent") { rtorrent = { }; }; + + # Create user if set to default + users.users = mkIf (cfg.user == "flood") { + flood = { + inherit (cfg) group; + shell = pkgs.bashInteractive; + home = cfg.dataDir; + description = "flood Daemon user"; + isSystemUser = true; + }; + }; + + # Open firewall if option is set to do so. + networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ cfg.port ]; + + # The actual service + systemd.services.flood = { + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + description = "flood system service"; + serviceConfig = { + User = cfg.user; + Group = cfg.group; + Type = "simple"; + Restart = "on-failure"; + WorkingDirectory = cfg.dataDir; + ExecStart = + "${cfg.package}/bin/flood --baseuri ${cfg.baseURI} --rundir ${cfg.dataDir} --host ${cfg.host} --port ${ + toString cfg.port + } ${ + if cfg.ssl then "--ssl" else "" + } --auth ${cfg.authMode} --rtsocket ${cfg.rpcSocket} --allowedpath ${cfg.downloadDir}"; + }; + }; + + # This is needed to create the dataDir with the correct permissions. + systemd.tmpfiles.rules = + [ "d '${cfg.dataDir}' 0755 ${cfg.user} ${cfg.group} -" ]; + }; +} diff --git a/nixos/common/modules/gnome/default.nix b/nixos/common/modules/gnome/default.nix new file mode 100644 index 00000000..eb2d4f09 --- /dev/null +++ b/nixos/common/modules/gnome/default.nix @@ -0,0 +1,70 @@ +{ config, pkgs, lib, ... }: +with lib; +let cfg = config.services.v.gnome; +in { + options.services.v.gnome = { + enable = mkEnableOption "v.gnome"; + hm = mkOption { + type = types.bool; + default = true; + description = '' + Whether to enable home manager integration to set default dconf values + ''; + }; + }; + + config = mkIf cfg.enable { + services = { + xserver = { + enable = true; + excludePackages = [ pkgs.xterm ]; + + # Configure keymap in X11 + + layout = "us"; + xkbVariant = "altgr-intl"; + + + # Enable the GNOME Desktop Environment. + displayManager.gdm.enable = true; + desktopManager.gnome.enable = true; + }; + udev.packages = with pkgs; [ gnome.gnome-settings-daemon ]; + dbus.enable = true; + udisks2.enable = true; + }; + + # Add Home-manager dconf stuff + home-manager.sharedModules = mkIf cfg.hm [ ./hm.nix ]; + environment.gnome.excludePackages = + (with pkgs; [ gnome-photos gnome-tour gnome-connections ]) + ++ (with pkgs.gnome; [ + atomix # puzzle game + epiphany # web browser + geary # email reader + gedit # text editor + gnome-calendar + gnome-clocks + gnome-contacts + gnome-maps + gnome-music + gnome-notes + gnome-terminal + gnome-weather + hitori # sudoku game + iagno # go game + simple-scan # document scanner + tali # poker game + totem # video player + ]); + + # Services required for gnome + programs.dconf.enable = true; + + # Extra gnome packages + environment.systemPackages = with pkgs; [ + gnome.gnome-tweaks + gnome.gnome-boxes + ]; + }; +} diff --git a/nixos/common/modules/gnome/hm.nix b/nixos/common/modules/gnome/hm.nix new file mode 100644 index 00000000..babdec76 --- /dev/null +++ b/nixos/common/modules/gnome/hm.nix @@ -0,0 +1,132 @@ +{ lib, ... }: + +with lib.hm.gvariant; +let + inherit (builtins) attrNames map; + inherit (lib.attrsets) mapAttrs' nameValuePair; + generate_custom_keybindings = binds: + { + "org/gnome/settings-daemon/plugins/media-keys" = { + custom-keybindings = map (name: + "/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/${name}/") + (attrNames binds); + }; + } // mapAttrs' (name: + nameValuePair + "org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/${name}") + binds; +in { + xdg.mimeApps.enable = true; + xdg.mimeApps.defaultApplications = { + "text/plain" = "org.gnome.TextEditor.desktop"; + "application/pdf" = "org.gnome.Evince.desktop"; + + # Firefox + "text/html" = "firefox.desktop"; + "x-scheme-handler/http" = "firefox.desktop"; + "x-scheme-handler/https" = "firefox.desktop"; + "x-scheme-handler/chrome" = "firefox.desktop"; + "application/x-extension-htm" = "firefox.desktop"; + "application/x-extension-shtml" = "firefox.desktop"; + "application/xhtml+xml" = "firefox.desktop"; + "application/x-extension-xhtml" = "firefox.desktop"; + "application/x-extension-xht" = "firefox.desktop"; + "application/x-extension-html" = "firefox.desktop"; + + # Images + "image/bmp" = "org.gnome.eog.desktop"; + "image/gif" = "org.gnome.eog.desktop"; + "image/jpg" = "org.gnome.eog.desktop"; + "image/pjpeg" = "org.gnome.eog.desktop"; + "image/png" = "org.gnome.eog.desktop"; + "image/tiff" = "org.gnome.eog.desktop"; + "image/webp" = "org.gnome.eog.desktop"; + "image/x-bmp" = "org.gnome.eog.desktop"; + "image/x-gray" = "org.gnome.eog.desktop"; + "image/x-icb" = "org.gnome.eog.desktop"; + "image/x-ico" = "org.gnome.eog.desktop"; + "image/x-png" = "org.gnome.eog.desktop"; + "image/x-portable-anymap" = "org.gnome.eog.desktop"; + "image/x-portable-bitmap" = "org.gnome.eog.desktop"; + "image/x-portable-graymap" = "org.gnome.eog.desktop"; + "image/x-portable-pixmap" = "org.gnome.eog.desktop"; + "image/x-xbitmap" = "org.gnome.eog.desktop"; + "image/x-xpixmap" = "org.gnome.eog.desktop"; + "image/x-pcx" = "org.gnome.eog.desktop"; + "image/svg+xml" = "org.gnome.eog.desktop"; + "image/svg+xml-compressed" = "org.gnome.eog.desktop"; + "image/vnd.wap.wbmp" = "org.gnome.eog.desktop"; + "image/x-icns" = "org.gnome.eog.desktop"; + }; + + dconf.settings = { + "org/gnome/desktop/input-sources" = { + sources = [ (mkTuple [ "xkb" "us+altgr-intl" ]) ]; + xkb-options = [ "terminate:ctrl_alt_bksp" ]; + }; + + "org/gnome/desktop/peripherals/touchpad" = { + tap-to-click = true; + two-finger-scrolling-enabled = true; + }; + + "org/gnome/mutter" = { + attach-modal-dialogs = true; + dynamic-workspaces = false; + edge-tiling = true; + focus-change-on-pointer-rest = true; + workspaces-only-on-primary = true; + }; + + "org/gnome/mutter/keybindings" = { + toggle-tiled-left = [ "bracketleft" ]; + toggle-tiled-right = [ "bracketright" ]; + }; + + "org/gnome/shell/keybindings" = { toggle-overview = [ "d" ]; }; + + "org/gnome/desktop/interface" = { color-scheme = "prefer-dark"; }; + + "org/gnome/desktop/wm/preferences" = { + auto-raise = false; + num-workspaces = 6; + focus-mode = "sloppy"; + }; + + "org/gnome/desktop/wm/keybindings" = { + raise-or-lower = [ "s" ]; + switch-applications = [ "Tab" ]; + switch-applications-backward = [ "Tab" ]; + move-to-workspace-1 = [ "1" ]; + move-to-workspace-2 = [ "2" ]; + move-to-workspace-3 = [ "3" ]; + move-to-workspace-4 = [ "4" ]; + move-to-workspace-5 = [ "5" ]; + move-to-workspace-6 = [ "6" ]; + switch-to-workspace-1 = [ "1" ]; + switch-to-workspace-2 = [ "2" ]; + switch-to-workspace-3 = [ "3" ]; + switch-to-workspace-4 = [ "4" ]; + switch-to-workspace-5 = [ "5" ]; + switch-to-workspace-6 = [ "6" ]; + toggle-fullscreen = [ "M" ]; + toggle-maximized = [ "m" ]; + close = [ "Q" ]; + }; + + "org/gnome/tweaks" = { show-extensions-notice = false; }; + + "org/gnome/boxes" = { first-run = false; }; + } // generate_custom_keybindings { + "terminal" = { + binding = "Return"; + command = "kgx"; + name = "Open Terminal"; + }; + "firefox" = { + binding = "f"; + command = "firefox"; + name = "Open Firefox"; + }; + }; +} diff --git a/nixos/common/modules/meta.nix b/nixos/common/modules/meta.nix new file mode 100644 index 00000000..639d212d --- /dev/null +++ b/nixos/common/modules/meta.nix @@ -0,0 +1,43 @@ +{ lib, ... }: +with lib; +let + exposesOpts = { + options = { + domain = mkOption { + type = types.str; + example = ".example.com"; + description = '' + The domain under which this service should be available + ''; + }; + port = mkOption { + type = types.int; + default = 80; + example = 4242; + description = '' + The port under which the service runs on the host + ''; + }; + }; + }; +in +{ + options.meta = { + + exposes = mkOption { + type = with types; attrsOf (submodule exposesOpts); + description = '' + Exposed services + ''; + }; + + ipv4 = mkOption { + type = types.str; + description = '' + Own IPv4 Address + ''; + }; + }; + + config = { }; +} diff --git a/nixos/common/modules/nginx.nix b/nixos/common/modules/nginx.nix new file mode 100644 index 00000000..1159e212 --- /dev/null +++ b/nixos/common/modules/nginx.nix @@ -0,0 +1,32 @@ +{ lib, hosts, config, ... }: +with lib; +let cfg = config.services.v.nginx; +in { + options.services.v.nginx.autoExpose = + mkEnableOption "generate vhosts"; + + config = + let + + proxy = url: { + enableACME = true; + forceSSL = true; + locations."/" = { + proxyPass = url; + proxyWebsockets = true; + }; + }; + + hosts' = + filter (hasAttr "exposes") (attrValues hosts.${config.networking.domain}); + exposes = { ip, exposes, ... }: + map ({ domain, port ? 80 }: { inherit ip domain port; }) (attrValues exposes); + mkVhost = { ip, domain, port }: { + "${domain}" = proxy "http://${ip}:${toString port}"; + }; + vhosts = foldr (el: acc: acc // mkVhost el) { } (concatMap exposes hosts'); + in + mkIf cfg.autoExpose { + services.nginx.virtualHosts = vhosts; + }; +} diff --git a/nixos/common/modules/unpackerr.nix b/nixos/common/modules/unpackerr.nix new file mode 100644 index 00000000..4a8043ba --- /dev/null +++ b/nixos/common/modules/unpackerr.nix @@ -0,0 +1,328 @@ +{ config, pkgs, lib, ... }: +with lib; +let + cfg = config.services.unpackerr; + mkStarrOptions = { name, url }: { + url = mkOption { + type = types.str; + default = ""; + example = "${url}"; + description = '' + The URL to access ${name} + ''; + }; + apiKey = mkOption { + type = types.str; + default = ""; + description = '' + The API key for accessing ${name} + ''; + }; + paths = mkOption { + type = types.str; + default = ""; + example = "/downloads,/moreDownloads"; + description = '' + List of paths where content is downloaded for ${name} + ''; + }; + protocols = mkOption { + type = types.str; + default = "torrent"; + example = "torrent,usenet"; + description = '' + Protocols to process + ''; + }; + timeout = mkOption { + type = types.str; + default = "10s"; + description = '' + How long to wait for ${name} to respond + ''; + }; + deleteOrginal = mkOption { + type = types.bool; + default = false; + description = '' + Delete archives after import? + Recommend not setting this to true + ''; + }; + deleteDelay = mkOption { + type = types.str; + default = "5m"; + description = '' + Extracts are deleted this long after import. `-1` to disable. + ''; + }; + }; +in +{ + options.services.unpackerr = { + enable = mkEnableOption "unpackerr"; + + user = mkOption { + default = "unpackerr"; + type = types.str; + description = '' + User account under which unpackerr runs. + ''; + }; + + group = mkOption { + type = types.str; + default = "unpackerr"; + description = '' + Group under which unpackerr runs. + ''; + }; + + package = mkOption { + type = types.package; + default = pkgs.unpackerr; + defaultText = "pkgs.unpackerr"; + description = '' + The unpackerr package to use. + ''; + }; + + debug = mkOption { + type = types.bool; + default = false; + description = '' + Turns on more logs. + ''; + }; + + interval = mkOption { + type = types.str; + default = "2m"; + description = '' + How often apps are polled, recommended 1m to 5m + ''; + }; + + startDelay = mkOption { + type = types.str; + default = "1m"; + description = '' + Files are queued at least this long before extraction + ''; + }; + + retryDelay = mkOption { + type = types.str; + default = "5m"; + description = '' + Failed extractions are retried after at least this long + ''; + }; + + maxRetries = mkOption { + type = types.int; + default = 3; + description = '' + Times to retry failed extractions. `0` = unlimited. + ''; + }; + + parallel = mkOption { + type = types.int; + default = 1; + description = '' + Concurrent extractions, 1 is recommended. + ''; + }; + + fileMode = mkOption { + type = types.str; + default = "0644"; + description = '' + Extracted files are written with this mode + ''; + }; + + dirMode = mkOption { + type = types.str; + default = "0755"; + description = '' + Extracted folders are written with this mode + ''; + }; + + sonarr = mkStarrOptions { + name = "Sonarr"; + url = "http://localhost:8989"; + }; + + radarr = mkStarrOptions { + name = "Radarr"; + url = "http://localhost:7878"; + }; + + lidarr = mkStarrOptions { + name = "Lidarr"; + url = "http://localhost:8686"; + }; + + readarr = mkStarrOptions { + name = "Readarr"; + url = "http://localhost:8787"; + }; + + folder = { + path = mkOption { + type = types.str; + default = ""; + description = '' + folder path, not for Starr apps. + ''; + }; + extractPath = mkOption { + type = types.str; + default = ""; + description = '' + Where to extract to, Defaults to . + ''; + }; + deleteAfter = mkOption { + type = types.str; + default = ""; + example = "10m"; + description = '' + Delete extracted files and/or archives after this duration, `0` to disable. + ''; + }; + deleteOrginal = mkOption { + type = types.bool; + default = false; + description = '' + Delete archives after extraction + ''; + }; + deleteFiles = mkOption { + type = types.bool; + default = false; + description = '' + Delete extracted files after successful extraction + ''; + }; + moveBack = mkOption { + type = types.bool; + default = false; + description = '' + Move extracted items back into original folder + ''; + }; + }; + + extraConfig = mkOption { + type = types.attrs; + default = { }; + description = '' + Extra environment variables + ''; + example = { UN_WEBHOOK_0_URL = "http://example.com"; }; + }; + + environmentFile = mkOption { + type = types.nullOr types.path; + default = null; + description = lib.mdDoc '' + Environment file (see `systemd.exec(5)` + "EnvironmentFile=" section for the syntax) to define variables for unpackerr. + This option can be used to safely include secret keys into the unpackerr configuration. + ''; + }; + }; + + config = mkIf cfg.enable { + # Create group if set to default + users.groups = mkIf (cfg.group == "unpackerr") { unpackerr = { }; }; + + # Create user if set to default + users.users = mkIf (cfg.user == "unpackerr") { + unpackerr = { + inherit (cfg) group; + shell = pkgs.bashInteractive; + createHome = false; + description = "unpackerr Daemon user"; + isSystemUser = true; + }; + }; + + # The actual service + systemd.services.unpackerr = { + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + description = "unpackerr system service"; + # Filter out all unset variables else unpackerr complains + environment = filterAttrs (_n: v: stringLength v > 0) + { + # General options + UN_DEBUG = "${toString cfg.debug}"; + UN_INTERVAL = "${cfg.interval}"; + UN_START_DELAY = "${cfg.startDelay}"; + UN_RETRY_DELAY = "${cfg.retryDelay}"; + UN_MAX_RETRIES = "${toString cfg.maxRetries}"; + UN_PARALLEL = "${toString cfg.parallel}"; + UN_FILE_MODE = "${cfg.fileMode}"; + UN_DIR_MODE = "${cfg.dirMode}"; + + # Sonarr + UN_SONARR_0_URL = "${cfg.sonarr.url}"; + UN_SONARR_0_API_KEY = "${cfg.sonarr.apiKey}"; + UN_SONARR_0_PATHS_0 = "${cfg.sonarr.paths}"; + UN_SONARR_0_PROTOCOLS = "${cfg.sonarr.protocols}"; + UN_SONARR_0_TIMEOUT = "${cfg.sonarr.timeout}"; + UN_SONARR_0_DELETE_ORIG = "${toString cfg.sonarr.deleteOrginal}"; + UN_SONARR_0_DELETE_DELAY = "${cfg.sonarr.deleteDelay}"; + + # Radarr + UN_RADARR_0_URL = "${cfg.radarr.url}"; + UN_RADARR_0_API_KEY = "${cfg.radarr.apiKey}"; + UN_RADARR_0_PATHS_0 = "${cfg.radarr.paths}"; + UN_RADARR_0_PROTOCOLS = "${cfg.radarr.protocols}"; + UN_RADARR_0_TIMEOUT = "${cfg.radarr.timeout}"; + UN_RADARR_0_DELETE_ORIG = "${toString cfg.radarr.deleteOrginal}"; + UN_RADARR_0_DELETE_DELAY = "${cfg.radarr.deleteDelay}"; + + # Lidarr + UN_LIDARR_0_URL = "${cfg.lidarr.url}"; + UN_LIDARR_0_API_KEY = "${cfg.lidarr.apiKey}"; + UN_LIDARR_0_PATHS_0 = "${cfg.lidarr.paths}"; + UN_LIDARR_0_PROTOCOLS = "${cfg.lidarr.protocols}"; + UN_LIDARR_0_TIMEOUT = "${cfg.lidarr.timeout}"; + UN_LIDARR_0_DELETE_ORIG = "${toString cfg.lidarr.deleteOrginal}"; + UN_LIDARR_0_DELETE_DELAY = "${cfg.lidarr.deleteDelay}"; + + # Readarr + UN_READARR_0_URL = "${cfg.readarr.url}"; + UN_READARR_0_API_KEY = "${cfg.readarr.apiKey}"; + UN_READARR_0_PATHS_0 = "${cfg.readarr.paths}"; + UN_READARR_0_PROTOCOLS = "${cfg.readarr.protocols}"; + UN_READARR_0_TIMEOUT = "${cfg.readarr.timeout}"; + UN_READARR_0_DELETE_ORIG = "${toString cfg.readarr.deleteOrginal}"; + UN_READARR_0_DELETE_DELAY = "${cfg.readarr.deleteDelay}"; + + # Folder + UN_FOLDER_0_PATH = "${cfg.folder.path}"; + UN_FOLDER_0_EXTRACT_PATH = "${cfg.folder.extractPath}"; + UN_FOLDER_0_DELETE_AFTER = "${cfg.folder.deleteAfter}"; + UN_FOLDER_0_DELETE_ORIGINAL = "${toString cfg.folder.deleteOrginal}"; + UN_FOLDER_0_DELETE_FILES = "${toString cfg.folder.deleteFiles}"; + UN_FOLDER_0_MOVE_BACK = "${toString cfg.folder.moveBack}"; + } // cfg.extraConfig; + serviceConfig = { + User = cfg.user; + Group = cfg.group; + Type = "simple"; + Restart = "on-failure"; + ExecStart = "${cfg.package}/bin/unpackerr"; + } // optionalAttrs (cfg.environmentFile != null) { + EnvironmentFile = cfg.environmentFile; + }; + }; + }; +} diff --git a/nixos/common/modules/vault.nix b/nixos/common/modules/vault.nix new file mode 100644 index 00000000..4460ee75 --- /dev/null +++ b/nixos/common/modules/vault.nix @@ -0,0 +1,125 @@ +{ config, pkgs, lib, flat_hosts, inputs, ... }: +with lib; +let + cfg = config.services.v.vault; + hostIP = config.meta.ipv4; + + # Find all vault hosts that do not have the same IP as the current host + vault_hosts = + filter ({ tags ? [ ], ip ? "", ... }: (elem "vault" tags) && (ip != hostIP)) + flat_hosts; + cluster_config = concatStrings (map + ({ ip, ... }: '' + retry_join { + leader_api_addr = "http://${ip}:${toString cfg.port}" + } + '') + vault_hosts); +in +{ + options.services.v.vault = { + enable = mkEnableOption "v's vault"; + + node_id = mkOption { + type = types.str; + description = lib.mdDoc '' + The cluster node id of this node + ''; + }; + + openFirewall = mkOption { + type = types.bool; + default = false; + description = lib.mdDoc '' + Whether to open port `port` and `clusterPort` in the firewall for vault + ''; + }; + + port = mkOption { + type = types.int; + default = 8200; + description = lib.mdDoc '' + The port vault listens on + **note:** this has to be the same for all nodes in a cluster + ''; + }; + + clusterPort = mkOption { + type = types.int; + default = 8201; + description = lib.mdDoc '' + The cluster port vault listens on + **note:** this has to be the same for all nodes in a cluster + ''; + }; + + autoUnseal = mkOption { + type = types.bool; + default = false; + description = lib.mdDoc '' + Whether to auto-unseal this vault + ''; + }; + + autoUnsealKeysFile = mkOption { + type = types.str; + default = null; + example = "/var/lib/vault-unseal/keys.json"; + description = lib.mdDoc '' + auto unseal keys to use, has to be a json file with the following structure + ```json + { + keys = [ key_1, ..., key_n ] + } + ``` + ''; + }; + }; + + config = mkIf cfg.enable { + assertions = [{ + assertion = cfg.autoUnseal -> (cfg.autoUnsealKeysFile != null); + message = "If autoUnseal is enabled, a token path is required!"; + }]; + + networking.firewall.allowedTCPPorts = + mkIf cfg.openFirewall [ cfg.port cfg.clusterPort ]; + + services.vault = { + enable = true; + # bin version includes the UI + package = pkgs.vault-bin; + address = "0.0.0.0:${toString cfg.port}"; + storageBackend = "raft"; + storagePath = "/var/lib/vault-raft"; + storageConfig = '' + node_id = "${cfg.node_id}" + '' + cluster_config; + extraConfig = '' + ui = true + disable_mlock = true + api_addr = "http://${hostIP}:${toString cfg.port}" + cluster_addr = "http://${hostIP}:${toString cfg.clusterPort}" + ''; + }; + + systemd.services.vault-unseal = mkIf cfg.autoUnseal { + description = "Vault unseal service"; + wantedBy = [ "multi-user.target" ]; + after = [ "vault.service" ]; + environment = { + VAULT_ADDR = "http://localhost:${toString cfg.port}"; + VAULT_KEY_FILE = cfg.autoUnsealKeysFile; + }; + serviceConfig = { + User = "vault"; + Group = "vault"; + Type = "simple"; + Restart = "on-failure"; + ExecStart = "${ + inputs.vault-unseal.packages.${pkgs.system}.default + }/bin/vault-unseal"; + }; + }; + }; +} diff --git a/nixos/common/users/default.nix b/nixos/common/users/default.nix new file mode 100644 index 00000000..d1f0b821 --- /dev/null +++ b/nixos/common/users/default.nix @@ -0,0 +1,55 @@ +{ config, pkgs, lib, ... }: { + imports = [ ./laura.nix ./vivian.nix ./jonathan.nix ]; + + # Setup ZSH to use grml config + programs.zsh = { + enable = true; + enableCompletion = true; + syntaxHighlighting.enable = true; + interactiveShellInit = '' + source "${pkgs.grml-zsh-config}/etc/zsh/zshrc" + export FZF_DEFAULT_COMMAND="${pkgs.ripgrep}/bin/rg --files --follow" + source "${pkgs.fzf}/share/fzf/key-bindings.zsh" + source "${pkgs.fzf}/share/fzf/completion.zsh" + eval "$(${pkgs.zoxide}/bin/zoxide init zsh)" + ''; + # otherwise it'll override the grml prompt + promptInit = ""; + }; + + environment.pathsToLink = [ "/share/zsh" ]; + + # Install Neovim and set it as alias for vi(m) + programs.neovim = { + enable = true; + viAlias = true; + vimAlias = true; + defaultEditor = true; + }; + + # Disable sudo prompt for `wheel` users. + security.sudo.wheelNeedsPassword = lib.mkDefault false; + + # Configure the root account + users.extraUsers.root = { + # Allow my SSH keys for logging in as root. + openssh.authorizedKeys.keys = + config.users.extraUsers.vivian.openssh.authorizedKeys.keys; + # Also use zsh for root + shell = pkgs.zsh; + }; + + # Setup packages available everywhere + environment.systemPackages = with pkgs; [ + fzf + git + htop + ncdu + psmisc + ripgrep + rsync + tmux + zoxide + tmux + ]; +} diff --git a/nixos/common/users/jonathan.nix b/nixos/common/users/jonathan.nix new file mode 100644 index 00000000..f5ac50d4 --- /dev/null +++ b/nixos/common/users/jonathan.nix @@ -0,0 +1,13 @@ +{ pkgs, ... }: { + users.extraUsers.jonathan = { + isNormalUser = true; + shell = pkgs.zsh; + + openssh.authorizedKeys.keys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOAXOTU6E06zjK/zkzlSPhTG35PoNRYgTCStEPUYyjeE jonathan@kili" + ]; + + extraGroups = [ ]; + }; +} + diff --git a/nixos/common/users/laura.nix b/nixos/common/users/laura.nix new file mode 100644 index 00000000..6c19947c --- /dev/null +++ b/nixos/common/users/laura.nix @@ -0,0 +1,14 @@ +{ pkgs, ... }: { + users.extraUsers.laura = { + isNormalUser = true; + shell = pkgs.zsh; + + openssh.authorizedKeys.keys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBIlFUUXbwOkhNUjoA6zueTdRuaylgpgFqSe/xWGK9zb laura@zmeura" + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBVkk9/80askWhInQk03JMntF6SThAYkFZNm+lIGt4E7 laura@mura" + ]; + + extraGroups = [ ]; + }; +} + diff --git a/nixos/common/users/vivian.nix b/nixos/common/users/vivian.nix new file mode 100644 index 00000000..35138b2f --- /dev/null +++ b/nixos/common/users/vivian.nix @@ -0,0 +1,48 @@ +{ pkgs, ... }: { + # The block that specifies my user account. + users.extraUsers.vivian = { + uid = 1000; + # This account is intended for a non-system user. + isNormalUser = true; + + # My default shell + shell = pkgs.zsh; + + # My SSH keys. + openssh.authorizedKeys.keys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICBhJAp7NWlHgwDYd2z6VNROy5RkeZHRINFLsFvwT4b3 vivian@bastion" + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMMbdjysLnmwJD5Fs/SjBPstdIQNUxy8zFHP0GlhHMJB vivian@bastion" + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIfooZjMWXvXZu1ReOEACDZ0TMb2WJRBSOLlWE8y6fUh vivian@aoife" + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBMTCUjDbDjAiEKbKmLPavuYM0wJIBdjgytLsg1uWuGc vivian@nord" + "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIM3TqXaApX2JZsgfZd7PKVFMecDgqTHKibpSzgdXNpYAAAAABHNzaDo= solov2-le" + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAID+HbsgJTQS6pvnMEI5NPKjIf78z+9A7CTIt3abi+PS6 vivian@eevee" + ]; + + # Make me admin + extraGroups = + [ "systemd-journal" "wheel" "networkmanager" "libvirtd" "dialout" ]; + }; + + home-manager.users.vivian = { + programs = { + home-manager.enable = true; + + v.git.enable = true; + + tmux = { + enable = true; + shortcut = "b"; + terminal = "screen-256color"; + clock24 = true; + }; + + bat.enable = true; + }; + home = { + username = "vivian"; + homeDirectory = "/home/vivian"; + stateVersion = "23.05"; + }; + + }; +} diff --git a/nixos/hosts/README.md b/nixos/hosts/README.md new file mode 100644 index 00000000..03d88a9b --- /dev/null +++ b/nixos/hosts/README.md @@ -0,0 +1,2 @@ +# NixOS Hosts +Each folder here is a separate geographical location, with `thalassa` being for roaming devices like laptops diff --git a/nixos/hosts/default.nix b/nixos/hosts/default.nix new file mode 100644 index 00000000..7859c057 --- /dev/null +++ b/nixos/hosts/default.nix @@ -0,0 +1,5 @@ +{ + hades = import ./hades; + olympus = import ./olympus; + thalassa = import ./thalassa; +} diff --git a/nixos/hosts/hades/_template/configuration.nix b/nixos/hosts/hades/_template/configuration.nix new file mode 100644 index 00000000..b1c2ee42 --- /dev/null +++ b/nixos/hosts/hades/_template/configuration.nix @@ -0,0 +1,22 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ pkgs, ... }: + +{ + imports = [ ]; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "23.11"; # Did you read the comment? + + # Additional packages + environment.systemPackages = with pkgs; [ ]; + + networking.firewall.allowedTCPPorts = [ ]; +} diff --git a/nixos/hosts/hades/attic/configuration.nix b/nixos/hosts/hades/attic/configuration.nix new file mode 100644 index 00000000..7b088d38 --- /dev/null +++ b/nixos/hosts/hades/attic/configuration.nix @@ -0,0 +1,93 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ pkgs, config, ... }: +let vs = config.vault-secrets.secrets; +in { + imports = [ ]; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "23.11"; # Did you read the comment? + + # Additional packages + environment.systemPackages = with pkgs; [ ]; + + vault-secrets.secrets.attic = { services = [ "atticd" ]; }; + + services.postgresql = { + enable = true; + package = pkgs.postgresql_15; + ensureDatabases = [ "atticd" ]; + ensureUsers = [{ + name = "atticd"; + ensurePermissions = { + "DATABASE atticd" = "ALL PRIVILEGES"; + "schema public" = "ALL"; + }; + }]; + + }; + + services.atticd = { + enable = true; + + credentialsFile = "${vs.attic}/environment"; + + settings = { + listen = "[::]:8080"; + allowed-hosts = [ "attic.xirion.net" ]; + api-endpoint = "https://attic.xirion.net/"; + require-proof-of-possession = false; + + garbage-collection = { + interval = "12 hours"; + default-retention-period = "1 month"; + }; + + compression = { + type = "zstd"; + level = 8; + }; + + database.url = "postgresql://atticd?host=/run/postgresql"; + + storage = { + type = "s3"; + region = "hades"; + bucket = "attic"; + endpoint = "http://garage.hades:3900"; + }; + + # Data chunking + # + # Warning: If you change any of the values here, it will be + # difficult to reuse existing chunks for newly-uploaded NARs + # since the cutpoints will be different. As a result, the + # deduplication ratio will suffer for a while after the change. + chunking = { + # The minimum NAR size to trigger chunking + # + # If 0, chunking is disabled entirely for newly-uploaded NARs. + # If 1, all NARs are chunked. + nar-size-threshold = 64 * 1024; # 64 KiB + + # The preferred minimum size of a chunk, in bytes + min-size = 16 * 1024; # 16 KiB + + # The preferred average size of a chunk, in bytes + avg-size = 64 * 1024; # 64 KiB + + # The preferred maximum size of a chunk, in bytes + max-size = 256 * 1024; # 256 KiB + }; + }; + }; + + networking.firewall.allowedTCPPorts = [ 8080 ]; +} diff --git a/nixos/hosts/hades/bastion/configuration.nix b/nixos/hosts/hades/bastion/configuration.nix new file mode 100644 index 00000000..ab13ad55 --- /dev/null +++ b/nixos/hosts/hades/bastion/configuration.nix @@ -0,0 +1,29 @@ +{ pkgs, lib, ... }: { + networking.interfaces.eth0.useDHCP = true; + + # mosh ssh + programs.mosh.enable = true; + + environment.systemPackages = with pkgs; [ + cachix + clang + direnv + git-crypt + nix-update + pinentry-curses + ripgrep + rsync + rustup + tmux + vault + ]; + + environment.noXlibs = lib.mkForce false; + + system.stateVersion = "22.11"; + + programs.gnupg.agent = { + enable = true; + pinentryFlavor = "curses"; + }; +} diff --git a/nixos/hosts/hades/bazarr/configuration.nix b/nixos/hosts/hades/bazarr/configuration.nix new file mode 100644 index 00000000..9b101adf --- /dev/null +++ b/nixos/hosts/hades/bazarr/configuration.nix @@ -0,0 +1,14 @@ +_: { + system.stateVersion = "22.11"; + networking.interfaces.eth0.useDHCP = true; + + fileSystems."/mnt/storage" = { + device = "storage:/mnt/storage"; + fsType = "nfs"; + }; + + services.bazarr = { + enable = true; + openFirewall = true; + }; +} diff --git a/nixos/hosts/hades/database/configuration.nix b/nixos/hosts/hades/database/configuration.nix new file mode 100644 index 00000000..a81fa520 --- /dev/null +++ b/nixos/hosts/hades/database/configuration.nix @@ -0,0 +1,38 @@ +{ config, pkgs, ... }: +let vs = config.vault-secrets.secrets; +in { + + system.stateVersion = "21.05"; + networking.interfaces.eth0.useDHCP = true; + + networking.firewall.allowedTCPPorts = [ config.services.postgresql.port ]; + + vault-secrets.secrets.database = { + user = "postgres"; + group = "postgres"; + services = [ "postgresql" ]; + }; + + services.postgresql = { + enable = true; + package = pkgs.postgresql_13; + enableTCPIP = true; + extraPlugins = [ ]; + initdbArgs = [ + "--encoding 'UTF-8'" + "--lc-collate='en_US.UTF-8'" + "--lc-ctype='en_US.UTF-8'" + ]; + authentication = '' + host all all 192.168.0.1/23 md5 + host all all 10.10.10.0/24 md5 + ''; + initialScript = "${vs.database}/initialScript"; + settings = { + shared_preload_libraries = "pg_stat_statements"; + "pg_stat_statements.track" = "all"; + "pg_stat_statements.max" = 10000; + track_activity_query_size = 2048; + }; + }; +} diff --git a/nixos/hosts/hades/default.nix b/nixos/hosts/hades/default.nix new file mode 100644 index 00000000..ba83fad4 --- /dev/null +++ b/nixos/hosts/hades/default.nix @@ -0,0 +1,172 @@ +{ + "opnsense" = { + ip = "192.168.0.1"; + mac = "00:0d:b9:56:b1:d8"; + nix = false; + }; + "nyx-bmc" = { + ip = "192.168.0.99"; + mac = "d0:50:99:f3:fa:42"; + nix = false; + }; + "nyx" = { + ip = "192.168.0.100"; + mac = "d0:50:99:de:99:4c"; + nix = false; + }; + "unifi" = { + ip = "192.168.0.101"; + mac = "5a:00:b7:6c:d1:e2"; + }; + "plex" = { + ip = "192.168.0.102"; + mac = "00:0c:29:a1:4e:28"; + nix = false; + }; + "vault-0" = { + ip = "192.168.0.103"; + mac = "7A:14:15:ED:D1:E6"; + tags = [ "vault" ]; + }; + "pmm" = { + ip = "192.168.0.104"; + mac = "7A:A3:59:1D:69:07"; + }; + "overseerr" = { + ip = "192.168.0.105"; + mac = "8E:21:7F:88:3A:83"; + }; + "tautulli" = { + ip = "192.168.0.106"; + mac = "BE:30:DB:F8:C6:55"; + }; + "dns-1" = { + ip = "192.168.0.107"; + mac = "12:84:3B:E0:8A:A0"; + profile = "dns"; + tags = [ "networking" ]; + }; + "dns-2" = { + ip = "192.168.0.108"; + mac = "56:C3:9C:A5:41:81"; + profile = "dns"; + tags = [ "networking" ]; + }; + "MariaDB" = { + ip = "192.168.0.109"; + mac = "00:0c:29:23:4f:12"; + nix = false; + }; + "bitwarden_rs" = { + ip = "192.168.0.110"; + mac = "00:0c:29:f5:98:00"; + nix = false; + }; + "rtorrent" = { + ip = "192.168.0.111"; + mac = "7a:5f:9b:62:49:91"; + }; + "cshub2" = { + ip = "192.168.0.113"; + mac = "26:8c:f6:f4:21:76"; + nix = false; + }; + "bastion" = { + ip = "192.168.0.114"; + mac = "66:14:8e:b2:50:c4"; + }; + "storage" = { + ip = "192.168.0.115"; + mac = "00:50:56:91:0d:69"; + nix = false; + }; + "immich" = { + ip = "192.168.0.116"; + mac = "06:8a:8e:3e:43:45"; + }; + "thelounge" = { + ip = "192.168.0.117"; + mac = "00:0c:29:2a:69:8f"; + nix = false; + }; + "mail" = { + ip = "192.168.0.118"; + mac = "00:50:56:91:3b:03"; + nix = false; + }; + "bazarr" = { + ip = "192.168.0.119"; + mac = "DE:7C:32:7E:DD:A1"; + }; + "plex2" = { + ip = "192.168.0.120"; + mac = "A2:2C:65:32:54:8A"; + profile = "plex"; + }; + "garage" = { + ip = "192.168.0.121"; + mac = "3A:19:32:A2:F8:96"; + }; + "nginx" = { + ip = "192.168.0.122"; + mac = "52:8E:72:31:AE:AC"; + }; + "reverseproxy" = { + ip = "192.168.0.123"; + mac = "00:0c:29:9b:10:82"; + nix = false; + }; + "pve-storage" = { + ip = "192.168.0.124"; + mac = "d4:3d:7e:35:0a:bf"; + nix = false; + }; + "lucy" = { + ip = "192.168.0.125"; + mac = "5E:36:04:2D:38:DF"; + type = "vm"; + }; + "database" = { + ip = "192.168.0.126"; + mac = "82:e8:71:7f:37:b4"; + }; + "dn42" = { + ip = "192.168.0.127"; + mac = "12:fa:24:02:65:e6"; + nix = false; + }; + "attic" = { + ip = "192.168.0.128"; + mac = "9E:AF:E9:FE:D4:D9"; + }; + "hassio" = { + ip = "192.168.0.129"; + mac = "e6:80:32:fb:00:75"; + nix = false; + }; + # "docker-registry" = { + # ip = "192.168.0.130"attic, ; + # mac = "5e:0e:a6:cf:64:70"; + # }; + "minecraft" = { + ip = "192.168.0.131"; + mac = "00:0c:29:9b:e1:c4"; + nix = false; + }; + # ip = "192.168.0.132"; + "mastodon" = { + ip = "192.168.0.138"; + mac = "52:60:8a:06:86:9c"; + }; + # ip = "192.168.0.140"; + "archlinux" = { + ip = "192.168.0.200"; + mac = "00:0c:29:e4:0d:17"; + nix = false; + }; + "HP781AFC" = { + ip = "192.168.0.201"; + mac = "f4:ce:46:78:1a:fc"; + nix = false; + }; +} diff --git a/nixos/hosts/hades/dns/configuration.nix b/nixos/hosts/hades/dns/configuration.nix new file mode 100644 index 00000000..89df9fee --- /dev/null +++ b/nixos/hosts/hades/dns/configuration.nix @@ -0,0 +1,50 @@ +{ pkgs, ... }: { + imports = [ ]; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "23.05"; # Did you read the comment? + + # Additional packages + environment.systemPackages = with pkgs; [ dig dogdns ]; + + services.v.dns = { + enable = true; + openFirewall = true; + mode = "server"; + }; + + services.unbound.settings.server = { + local-zone = [ + "xirion.net typetransparent" + "attic.xirion.net typetransparent" + "o.xirion.net typetransparent" + "attic.xirion.net typetransparent" + "g.xirion.net typetransparent" + "fedi-media.xirion.net typetransparent" + "hades.xirion.net typetransparent" + "requests.xirion.net typetransparent" + "ha.xirion.net typetransparent" + "mail.xirion.net typetransparent" + "plex.xirion.net typetransparent" + ]; + + local-data = [ + ''"xirion.net A 192.168.0.122"'' + ''"attic.xirion.net A 192.168.0.122"'' + ''"hades.xirion.net A 192.168.0.122"'' + ''"o.xirion.net A 192.168.0.122"'' + ''"attic.xirion.net A 192.168.0.122"'' + ''"g.xirion.net A 192.168.0.122"'' + ''"fedi-media.xirion.net A 192.168.0.122"'' + ''"requests.xirion.net A 192.168.0.122"'' + ''"ha.xirion.net A 192.168.0.122"'' + ''"mail.xirion.net A 192.168.0.122"'' + ''"plex.xirion.net A 192.168.0.122"'' + ]; + }; +} diff --git a/nixos/hosts/hades/garage/configuration.nix b/nixos/hosts/hades/garage/configuration.nix new file mode 100644 index 00000000..ca090ca6 --- /dev/null +++ b/nixos/hosts/hades/garage/configuration.nix @@ -0,0 +1,53 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ pkgs, config, ... }: +let vs = config.vault-secrets.secrets; +in { + imports = [ ]; + + vault-secrets.secrets.garage = { }; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "23.11"; # Did you read the comment? + + # Additional packages + environment.systemPackages = with pkgs; [ ]; + + networking.firewall.allowedTCPPorts = [ 3900 3901 3902 ]; + + # Defines rpc_secret + systemd.services.garage.serviceConfig.EnvironmentFile = [ "${vs.garage}/environment" ]; + + services.garage = { + enable = true; + package = pkgs.garage_0_8; + settings = { + db_engine = "lmdb"; # Recommended for mastodon + replication_mode = "1"; + compression_level = 0; + + # For inter-node comms + rpc_bind_addr = "[::]:3901"; + rpc_public_addr = "${config.meta.ipv4}:3901"; + + # Standard S3 api endpoint + s3_api = { + s3_region = "hades"; + api_bind_addr = "[::]:3900"; + }; + + # Static file serve endpoint + s3_web = { + bind_addr = "[::]:3902"; + root_domain = "g.xirion.net"; + }; + }; + }; +} diff --git a/nixos/hosts/hades/immich/configuration.nix b/nixos/hosts/hades/immich/configuration.nix new file mode 100644 index 00000000..4434cf27 --- /dev/null +++ b/nixos/hosts/hades/immich/configuration.nix @@ -0,0 +1,73 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ pkgs, config, ... }: +let + # https://github.com/immich-app/immich/releases + # version = "1.55.1"; + dataDir = "/var/lib/immich"; +in +{ + imports = [ ]; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "23.05"; # Did you read the comment? + + # Additional packages + environment.systemPackages = with pkgs; [ ]; + + + + # TODO: https://github.com/suderman/nixos/tree/main/modules/nixos/immich + + fileSystems."/mnt/storage" = { + device = "storage:/mnt/storage"; + fsType = "nfs"; + }; + + # Unused uid/gid snagged from this list: + # https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/misc/ids.nix + ids.uids.immich = 911; + ids.gids.immich = 911; + + users.groups.photos = {}; + + users.users.immich = { + isSystemUser = true; + group = "photos"; + description = "Immich daemon user"; + home = dataDir; + uid = config.ids.uids.immich; + }; + + users.groups.immich = { gid = config.ids.gids.immich; }; + + # Postgres database configuration + services.postgresql = { + enable = true; + + package = pkgs.postgresql_15; + + ensureUsers = [{ + name = "immich"; + ensurePermissions = { "DATABASE immich" = "ALL PRIVILEGES"; }; + }]; + ensureDatabases = [ "immich" ]; + + # Allow connections from any docker IP addresses + authentication = '' + host immich immich 172.16.0.0/12 md5 + host all all 127.0.0.1/32 ident + ''; + + }; + + # Allow docker containers to connect + networking.firewall.allowedTCPPorts = [ config.services.postgresql.port ]; +} diff --git a/nixos/hosts/hades/lucy/configuration.nix b/nixos/hosts/hades/lucy/configuration.nix new file mode 100644 index 00000000..f73a5df8 --- /dev/null +++ b/nixos/hosts/hades/lucy/configuration.nix @@ -0,0 +1,75 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ pkgs, ... }: +let + # Redefining the package instead of overriding as overriding GoModules seems broken + # see: https://github.com/NixOS/nixpkgs/issues/86349 + nuclei-latest = pkgs.buildGoModule rec { + pname = "nuclei"; + version = "2.9.2"; + + src = pkgs.fetchFromGitHub { + owner = "projectdiscovery"; + repo = pname; + rev = "1f9a065713924b28b203e2108fc76d7a1ec49068"; + hash = "sha256-QiegMoBy0gZMyQl2MRAwR14zXeh8wvVonyETdAzHbj0="; + }; + + vendorHash = "sha256-0JNwoBqLKH1F/0Tr8o35gCSNT/2plIjIQvZRuzAZ5P8="; + + modRoot = "./v2"; + subPackages = [ "cmd/nuclei/" ]; + + doCheck = false; + }; +in +{ + imports = [ ./hardware-configuration.nix ]; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "23.05"; # Did you read the comment? + + # Additional packages + environment.systemPackages = with pkgs; [ + ffuf + gcc + go + jq + nuclei-latest + rustup + trivy + wapiti + ]; + boot.loader = { + + systemd-boot.enable = true; + efi.canTouchEfiVariables = true; + efi.efiSysMountPoint = "/boot"; + }; + + virtualisation.docker.enable = true; + + services.mosquitto = { + enable = true; + listeners = [{ + acl = [ "pattern readwrite #" ]; + omitPasswordAuth = true; + settings.allow_anonymous = true; + }]; + }; + + networking.firewall = { + enable = true; + allowedTCPPorts = [ 1883 ]; + }; + + users.extraUsers.laura.extraGroups = [ "wheel" "docker" ]; + users.extraUsers.vivian.extraGroups = [ "docker" ]; +} diff --git a/nixos/hosts/hades/lucy/hardware-configuration.nix b/nixos/hosts/hades/lucy/hardware-configuration.nix new file mode 100644 index 00000000..ba51cd13 --- /dev/null +++ b/nixos/hosts/hades/lucy/hardware-configuration.nix @@ -0,0 +1,44 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ lib, modulesPath, ... }: + +{ + imports = [ (modulesPath + "/profiles/qemu-guest.nix") ]; + boot = { + + initrd.availableKernelModules = [ + "uhci_hcd" + "ehci_pci" + "ahci" + "virtio_pci" + "virtio_scsi" + "sd_mod" + "sr_mod" + ]; + initrd.kernelModules = [ ]; + kernelModules = [ ]; + extraModulePackages = [ ]; + }; + + fileSystems."/" = { + device = "/dev/disk/by-uuid/749c02fd-209d-4974-917e-38b749d10ec2"; + fsType = "ext4"; + }; + + fileSystems."/boot" = { + device = "/dev/disk/by-uuid/D021-72EB"; + fsType = "vfat"; + }; + + swapDevices = [ ]; + + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces..useDHCP`. + networking.useDHCP = lib.mkDefault true; + # networking.interfaces.enp6s18.useDHCP = lib.mkDefault true + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; +} diff --git a/nixos/hosts/hades/mastodon/configuration.nix b/nixos/hosts/hades/mastodon/configuration.nix new file mode 100644 index 00000000..eee7fde6 --- /dev/null +++ b/nixos/hosts/hades/mastodon/configuration.nix @@ -0,0 +1,107 @@ +{ config, pkgs, lib, ... }: +let + vs = config.vault-secrets.secrets; + cfg = config.services.mastodon; +in +{ + system.stateVersion = "21.05"; + # Use DHCP with static leases + networking.interfaces.eth0.useDHCP = true; + + # Better cache hits + environment.noXlibs = lib.mkForce false; + + services.elasticsearch = { + enable = true; + cluster_name = "mastodon-es"; + package = pkgs.elasticsearch7; + }; + + vault-secrets.secrets.mastodon = { + services = [ "mastodon-init-dirs" "mastodon" "mastodon-media-autoremove" ]; + inherit (cfg) user group; + }; + + # Append the init-dirs script to add AWS/Minio secrets + systemd.services.mastodon-init-dirs.script = '' + cat >> /var/lib/mastodon/.secrets_env <> + sort_title: <> + sync_mode: sync + smart_label: release.desc + Set: + optional: + - collection + - movie + - list + - background + - poster + tmdb_collection_details: <> + tmdb_movie: <> + tmdb_list: <> + sync_mode: sync + collection_order: release + url_poster: <> + sort_title: <> + url_background: <> +collections: + Marvel Cinematic Universe: + tvdb_list: https://thetvdb.com/lists/marvel-cinematic-universe + template: + name: Set + poster: https://theposterdb.com/api/assets/162417 + Star Wars: + template: + name: Set + collection: 10 + poster: https://theposterdb.com/api/assets/164120 + Studio Ghibli: + template: { name: Studio, company: 10342 } + url_poster: https://theposterdb.com/api/assets/393 + Pixar: + template: { name: Studio, company: 3 } + url_poster: https://theposterdb.com/api/assets/18894 + Star Trek: + tmdb_collection: + - 151 + - 115570 + template: + name: Set + poster: https://theposterdb.com/api/assets/222279 + background: https://i.imgur.com/Yp0NCZa.jpg + Bad Trek: + template: + name: Set + collection: 115575 + National Theatre: + imdb_list: https://www.imdb.com/search/title/?companies=co0388435 + template: + name: Studio + company: 16355 diff --git a/nixos/hosts/hades/pmm/config/TVShows.yml b/nixos/hosts/hades/pmm/config/TVShows.yml new file mode 100644 index 00000000..9b7dcb22 --- /dev/null +++ b/nixos/hosts/hades/pmm/config/TVShows.yml @@ -0,0 +1,38 @@ +templates: + set: + optional: + - network + - list + - poster + - background + tmdb_network: <> + tmdb_list: <> + sort_title: <> + sync_mode: sync + url_poster: <> + url_background: <> + +collections: + Marvel Cinematic Universe: + tvdb_list: https://thetvdb.com/lists/marvel-cinematic-universe + template: + name: set + poster: https://theposterdb.com/api/assets/239453 + background: https://i.imgur.com/ckx6reE.jpg + summary: Marvel Television + + Star Wars: + tvdb_list: https://thetvdb.com/lists/star-wars + template: + name: set + poster: https://theposterdb.com/api/assets/164120 + background: https://i.imgur.com/OvxROTE.jpg + summary: Star Wars + + Star Trek: + tvdb_list: https://thetvdb.com/lists/star-trek + template: + name: set + poster: https://theposterdb.com/api/assets/222279 + background: https://i.imgur.com/Yp0NCZa.jpg + summary: Star Trek diff --git a/nixos/hosts/hades/pmm/configuration.nix b/nixos/hosts/hades/pmm/configuration.nix new file mode 100644 index 00000000..3d9cc038 --- /dev/null +++ b/nixos/hosts/hades/pmm/configuration.nix @@ -0,0 +1,50 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ config, pkgs, ... }: +let + datadir = "/var/lib/pmm/config"; + container = config.virtualisation.oci-containers.containers.plex-meta-manager.image; + run_pmm = pkgs.writeScriptBin "pmm-run" '' + sudo ${pkgs.podman}/bin/podman run -d --rm -it \ + -v "/var/lib/pmm/config:/config:rw" \ + -v "/etc/pmm/Anime.yml:/config/Anime.yml:ro" \ + -v "/etc/pmm/Movies.yml:/config/Movies.yml:ro" \ + -v "/etc/pmm/TVShows.yml:/config/TVShows.yml:ro" \ + ${container} --run + ''; +in +{ + imports = [ ]; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "22.11"; # Did you read the comment? + + networking.firewall.allowedTCPPorts = [ ]; + + environment.etc.pmm.source = ./config; + + environment.systemPackages = [ run_pmm ]; + + virtualisation.podman.enable = true; + virtualisation.oci-containers = { + backend = "podman"; + containers = { + plex-meta-manager = { + image = "meisnate12/plex-meta-manager:v1.19.1"; + volumes = [ + "${datadir}:/config:rw" + "/etc/pmm/Anime.yml:/config/Anime.yml:ro" + "/etc/pmm/Movies.yml:/config/Movies.yml:ro" + "/etc/pmm/TVShows.yml:/config/TVShows.yml:ro" + ]; + }; + }; + }; +} diff --git a/nixos/hosts/hades/rtorrent/configuration.nix b/nixos/hosts/hades/rtorrent/configuration.nix new file mode 100644 index 00000000..af10331c --- /dev/null +++ b/nixos/hosts/hades/rtorrent/configuration.nix @@ -0,0 +1,53 @@ +{ config, pkgs, ... }: +let vs = config.vault-secrets.secrets; +in { + imports = [ ./rtorrent.nix ]; + + networking.interfaces.eth0.useDHCP = true; + system.stateVersion = "22.05"; + + networking.firewall.allowedTCPPorts = [ config.services.rtorrent.port ]; + networking.firewall.allowedUDPPorts = [ config.services.rtorrent.port ]; + + fileSystems."/mnt/storage" = { + device = "storage:/mnt/storage"; + fsType = "nfs"; + }; + + services.flood = { + enable = true; + host = "0.0.0.0"; + openFirewall = true; + inherit (config.services.rtorrent) downloadDir; + }; + + vault-secrets.secrets.rtorrent = { services = [ "wg-quick-wg0" ]; }; + + networking.wg-quick.interfaces = + let + postUpScript = pkgs.writeScriptBin "post_up" '' + #!${pkgs.stdenv.shell} + ${pkgs.iproute2}/bin/ip route add 10.42.42.0/23 via 192.168.0.1 + ${pkgs.iproute2}/bin/ip route add 10.100.0.0/24 via 192.168.0.1 + ''; + in + { + wg0 = { + address = [ "10.129.112.89/32, fd7d:76ee:e68f:a993:edd1:668b:49f7:b7c3/128" ]; + mtu = 1320; + dns = [ "10.128.0.1" "fd7d:76ee:e68f:a993::1" ]; + privateKeyFile = "${vs.rtorrent}/wireguardKey"; + postUp = "${postUpScript}/bin/post_up || true"; + + peers = [ + { + publicKey = "PyLCXAQT8KkM4T+dUsOQfn+Ub3pGxfGlxkIApuig+hk="; + allowedIPs = [ "0.0.0.0/0" "::/0" ]; + endpoint = "europe3.vpn.airdns.org:1637"; + presharedKeyFile = "${vs.rtorrent}/presharedKey"; + persistentKeepalive = 15; + } + ]; + }; + }; +} diff --git a/nixos/hosts/hades/rtorrent/rtorrent.nix b/nixos/hosts/hades/rtorrent/rtorrent.nix new file mode 100644 index 00000000..bfdd6a6b --- /dev/null +++ b/nixos/hosts/hades/rtorrent/rtorrent.nix @@ -0,0 +1,116 @@ +{ config, pkgs, ... }: { + services.rtorrent = { + enable = true; + port = 14764; # port forwarded + downloadDir = "/mnt/storage/torrents/r"; + package = pkgs.jesec-rtorrent; + configText = + let cfg = config.services.rtorrent; + in pkgs.lib.mkForce '' + # rTorrent runtime directory (cfg.basedir) [default: "$HOME/.local/share/rtorrent"] + method.insert = cfg.basedir, private|const|string, (cat,"${cfg.dataDir}/") + + # Default download directory (cfg.download) [default: "$(cfg.basedir)/download"] + method.insert = cfg.download, private|const|string, (cat,"${cfg.downloadDir}") + + # RPC Socket + method.insert = cfg.rpcsock, private|const|string, (cat,"${cfg.rpcSocket}") + + # Log directory (cfg.logs) [default: "$(cfg.basedir)/log"] + method.insert = cfg.logs, private|const|string, (cat,(cfg.basedir),"log/") + method.insert = cfg.logfile, private|const|string, (cat,(cfg.logs),"rtorrent-",(system.time),".log") + + # Torrent session directory (cfg.session) [default: "$(cfg.basedir)/.session"] + method.insert = cfg.session, private|const|string, (cat,(cfg.basedir),".session/") + + # Watch (drop to add) directories (cfg.watch) [default: "$(cfg.basedir)/watch"] + method.insert = cfg.watch, private|const|string, (cat,(cfg.basedir),"watch/") + + # Create directories + fs.mkdir.recursive = (cat,(cfg.basedir)) + + fs.mkdir = (cat,(cfg.download)) + fs.mkdir = (cat,(cfg.logs)) + fs.mkdir = (cat,(cfg.session)) + + fs.mkdir = (cat,(cfg.watch)) + fs.mkdir = (cat,(cfg.watch),"/load") + fs.mkdir = (cat,(cfg.watch),"/start") + + # Drop to "$(cfg.watch)/load" to add torrent + schedule2 = watch_load, 11, 10, ((load.verbose, (cat, (cfg.watch), "load/*.torrent"))) + + # Drop to "$(cfg.watch)/start" to add torrent and start downloading + schedule2 = watch_start, 10, 10, ((load.start_verbose, (cat, (cfg.watch), "start/*.torrent"))) + + # Listening port for incoming peer traffic + network.port_range.set = ${toString cfg.port}-${toString cfg.port} + network.port_random.set = no + + # Distributed Hash Table and Peer EXchange + dht.mode.set = disable + dht.port.set = 6881 + protocol.pex.set = yes + + # UDP tracker support + trackers.use_udp.set = yes + + # Peer settings + throttle.max_uploads.set = 100 + throttle.max_uploads.global.set = 250 + throttle.min_peers.normal.set = 20 + throttle.max_peers.normal.set = 60 + throttle.min_peers.seed.set = 30 + throttle.max_peers.seed.set = 80 + trackers.numwant.set = 80 + + protocol.encryption.set = allow_incoming,try_outgoing,enable_retry + + # Limits for file handle resources, this is optimized for + # an `ulimit` of 1024 (a common default). You MUST leave + # a ceiling of handles reserved for rTorrent's internal needs! + network.max_open_files.set = 600 + network.max_open_sockets.set = 300 + + # Memory resource usage (increase if you have a large number of items loaded, + # and/or the available resources to spend) + pieces.memory.max.set = 1800M + network.xmlrpc.size_limit.set = 32M + + # Basic operational settings + session.path.set = (cat, (cfg.session)) + directory.default.set = (cat, (cfg.download)) + log.execute = (cat, (cfg.logs), "execute.log") + + # Other operational settings + encoding.add = utf8 + system.umask.set = 0027 + system.cwd.set = (directory.default) + #schedule2 = low_diskspace, 5, 60, ((close_low_diskspace, 500M)) + #pieces.hash.on_completion.set = no + + # HTTP and SSL + network.http.max_open.set = 50 + network.http.dns_cache_timeout.set = 25 + + #network.http.ssl_verify_peer.set = 1 + #network.http.ssl_verify_host.set = 1 + + # Run the rTorrent process as a daemon in the background + system.daemon.set = true + + # XML-RPC interface + network.scgi.open_local = (cat,(cfg.rpcsock)) + schedule = scgi_group,0,0,"execute.nothrow=chown,\":rtorrent\",(cfg.rpcsock)" + schedule = scgi_permission,0,0,"execute.nothrow=chmod,\"g+w,o=\",(cfg.rpcsock)" + + # Logging: + # Levels = critical error warn notice info debug + # Groups = connection_* dht_* peer_* rpc_* storage_* thread_* tracker_* torrent_* + print = (cat, "Logging to ", (cfg.logfile)) + log.open_file = "log", (cfg.logfile) + log.add_output = "debug", "log" + ''; + }; +} + diff --git a/nixos/hosts/hades/tautulli/configuration.nix b/nixos/hosts/hades/tautulli/configuration.nix new file mode 100644 index 00000000..9976ee2a --- /dev/null +++ b/nixos/hosts/hades/tautulli/configuration.nix @@ -0,0 +1,23 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ ... }: + +{ + imports = [ ]; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "22.11"; # Did you read the comment? + + services.tautulli = { + enable = true; + port = 8080; + openFirewall = true; + }; +} diff --git a/nixos/hosts/hades/unifi/configuration.nix b/nixos/hosts/hades/unifi/configuration.nix new file mode 100644 index 00000000..ef1aaecc --- /dev/null +++ b/nixos/hosts/hades/unifi/configuration.nix @@ -0,0 +1,20 @@ +{ pkgs, lib, pkgs_stable, ... }: { + system.stateVersion = "21.05"; + networking.interfaces.eth0.useDHCP = true; + + environment.systemPackages = [ pkgs_stable.mongodb-4_2 ]; + + services.unifi = { + enable = true; + unifiPackage = pkgs.unifi; + mongodbPackage = pkgs_stable.mongodb-4_2; + openFirewall = true; + }; + + # Required for Java + # gets forced to true due the lxc profile + environment.noXlibs = lib.mkForce false; + + # Unifi Web Port + networking.firewall.allowedTCPPorts = [ 8443 ]; +} diff --git a/nixos/hosts/hades/vault-0/configuration.nix b/nixos/hosts/hades/vault-0/configuration.nix new file mode 100644 index 00000000..6eb1237f --- /dev/null +++ b/nixos/hosts/hades/vault-0/configuration.nix @@ -0,0 +1,23 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +_: { + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "21.05"; # Did you read the comment? + + # Vault + services.v.vault = { + enable = true; + openFirewall = true; + node_id = "hades-1"; + + autoUnseal = true; + autoUnsealKeysFile = "/var/lib/vault-unseal/keys.json"; + }; +} diff --git a/nixos/hosts/olympus/_template/configuration.nix b/nixos/hosts/olympus/_template/configuration.nix new file mode 100644 index 00000000..b1c2ee42 --- /dev/null +++ b/nixos/hosts/olympus/_template/configuration.nix @@ -0,0 +1,22 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ pkgs, ... }: + +{ + imports = [ ]; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "23.11"; # Did you read the comment? + + # Additional packages + environment.systemPackages = with pkgs; [ ]; + + networking.firewall.allowedTCPPorts = [ ]; +} diff --git a/nixos/hosts/olympus/bastion/configuration.nix b/nixos/hosts/olympus/bastion/configuration.nix new file mode 100644 index 00000000..40d78ead --- /dev/null +++ b/nixos/hosts/olympus/bastion/configuration.nix @@ -0,0 +1,74 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ pkgs, ... }: +let + fix-vscode = pkgs.writeScriptBin "fix-vscode" '' + #!${pkgs.stdenv.shell} + # Check if vscode-server dir exists + if [[ -d "$HOME/.vscode-server/bin" ]]; then + # For every bin folder within + for versiondir in "$HOME"/.vscode-server/bin/*; do + # Remove bundled node (dynamic links are borked for nix) + rm "$versiondir/node" + # symlink node form the nixpkg + ln -s "${pkgs.nodejs-16_x}/bin/node" "$versiondir/node" + done + fi + ''; +in +{ + imports = [ + # Include the results of the hardware scan. + ./hardware-configuration.nix + ]; + + # This _should_ fix vscode errors as well + programs.nix-ld.enable = true; + # environment.variables = { + # NIX_LD_LIBRARY_PATH = lib.makeLibraryPath [ + # pkgs.stdenv.cc.cc + # ]; + # # NIX_LD = lib.fileContents "${pkgs.stdenv.cc}/nix-support/dynamic-linker"; + # }; + + # Use the GRUB 2 boot loader. + boot.loader.grub.enable = true; + boot.loader.grub.device = "/dev/sda"; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "22.11"; # Did you read the comment? + + virtualisation.podman.enable = true; + + # Additional packages + environment.systemPackages = with pkgs; [ + binutils + fix-vscode + fluxcd + k9s + kubectl + kubectx + nix-prefetch-git + nixpkgs-fmt + nixpkgs-review + ripgrep + rsync + tmux + vault + vim + ]; + + programs.gnupg.agent = { + enable = true; + pinentryFlavor = "curses"; + }; + + home-manager.users.vivian = import ./home.nix; +} diff --git a/nixos/hosts/olympus/bastion/hardware-configuration.nix b/nixos/hosts/olympus/bastion/hardware-configuration.nix new file mode 100644 index 00000000..be7d9923 --- /dev/null +++ b/nixos/hosts/olympus/bastion/hardware-configuration.nix @@ -0,0 +1,25 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ modulesPath, ... }: + +{ + imports = [ (modulesPath + "/profiles/qemu-guest.nix") ]; + boot = { + + initrd.availableKernelModules = + [ "ata_piix" "uhci_hcd" "virtio_pci" "virtio_scsi" "sd_mod" "sr_mod" ]; + initrd.kernelModules = [ ]; + kernelModules = [ ]; + extraModulePackages = [ ]; + }; + + fileSystems."/" = { + device = "/dev/disk/by-uuid/e8427097-8545-4924-b033-2659fcf9adca"; + fsType = "ext4"; + }; + + swapDevices = + [{ device = "/dev/disk/by-uuid/63d90b92-cdde-4795-a3ab-9566ae88f43d"; }]; + +} diff --git a/nixos/hosts/olympus/bastion/home.nix b/nixos/hosts/olympus/bastion/home.nix new file mode 100644 index 00000000..a65de8e8 --- /dev/null +++ b/nixos/hosts/olympus/bastion/home.nix @@ -0,0 +1,11 @@ +_: { + programs.direnv = { + enable = true; + nix-direnv = { enable = true; }; + }; + + programs.zsh = { + enable = true; + sessionVariables = { DIRENV_LOG_FORMAT = ""; }; + }; +} diff --git a/nixos/hosts/olympus/ci/configuration.nix b/nixos/hosts/olympus/ci/configuration.nix new file mode 100644 index 00000000..0c80aac0 --- /dev/null +++ b/nixos/hosts/olympus/ci/configuration.nix @@ -0,0 +1,73 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ config, pkgs, ... }: +let vs = config.vault-secrets.secrets; +in { + imports = [ ]; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "22.11"; # Did you read the comment? + + # Additional packages + environment.systemPackages = with pkgs; [ ]; + + vault-secrets.secrets.gitea_runner = { + services = [ "gitea-runner-nix_native" "gitea-runner-runner_1" ]; + }; + + virtualisation.podman = { + enable = true; + dockerSocket.enable = true; + dockerCompat = true; + autoPrune.enable = true; + }; + + # Thanks to: https://blog.kotatsu.dev/posts/2023-04-21-woodpecker-nix-caching/ + + # Fix DNS Lookup in podman + virtualisation.podman.defaultNetwork.settings.dns_enable = true; + networking.firewall.interfaces."podman+" = { + allowedUDPPorts = [ 53 ]; + allowedTCPPorts = [ 53 ]; + }; + + services.gitea-actions-runner.instances = { + runner_1 = { + name = "runner_1"; + enable = true; + labels = [ "docker:docker://node:16-bullseye" ]; + url = "https://git.0x76.dev"; + tokenFile = "${vs.gitea_runner}/token_runner_1"; + }; + native_nix = { + enable = true; + name = "native_nix"; + labels = [ "native:host" ]; + url = "https://git.0x76.dev"; + tokenFile = "${vs.gitea_runner}/token_native"; + hostPackages = with pkgs; [ + bash + coreutils + curl + deadnix + gawk + gitMinimal + gnused + jq + nixUnstable + nodejs + statix + vault + wget + yamllint + ]; + }; + }; +} diff --git a/nixos/hosts/olympus/default.nix b/nixos/hosts/olympus/default.nix new file mode 100644 index 00000000..58b6d7e8 --- /dev/null +++ b/nixos/hosts/olympus/default.nix @@ -0,0 +1,218 @@ +{ + "edgerouter" = { + ip = "10.42.42.1"; + ip6 = "2001:41f0:9639:1:b6fb:e4ff:fe53:9c0"; + mac = "B4:FB:E4:53:9C:0A"; + nix = false; + }; + "unifi-ap" = { + ip = "10.42.42.2"; + mac = "b4:fb:e4:f3:ff:1b"; + nix = false; + }; + "dhcp" = { + ip = "10.42.42.3"; + mac = "3E:2D:E8:AA:E2:81"; + tags = [ "networking" ]; + }; + "bastion" = { + ip = "10.42.42.4"; + ip6 = "2001:41f0:9639:1:80f0:7cff:fecb:bd6d"; + mac = "82:F0:7C:CB:BD:6D"; + type = "vm"; + }; + "vault" = { + ip = "10.42.42.6"; + mac = "16:2B:87:55:0C:0C"; + profile = "vault-0"; + tags = [ "vault" ]; + }; + "mosquitto" = { + ip = "10.42.42.7"; + mac = "C6:F9:8B:3D:9E:37"; + }; + "home-assistant" = { + ip = "10.42.42.8"; + ip6 = "2001:41f0:9639:1:bfe7:3fd9:75de:cbee"; + mac = "9E:60:78:ED:81:B4"; + nix = false; + exposes.ha = { + domain = "ha.0x76.dev"; + port = 8123; + }; + }; + "nginx" = { + ip = "10.42.42.9"; + ip6 = "2001:41f0:9639:1:68c2:89ff:fe85:cfa6"; + mac = "6A:C2:89:85:CF:A6"; + tags = [ "web" ]; + }; + "kubernetes" = { + ip = "10.42.42.10"; + mac = "6E:A5:25:99:FE:68"; + exposes = { + www.domain = "0x76.dev"; + flux.domain = "flux.0x76.dev"; + internal.domain = "internal.xirion.net"; + blog.domain = "blog.xirion.net"; + }; + }; + "dex" = { + ip = "10.42.42.11"; + mac = "AE:66:7B:FA:15:72"; + exposes = { + dex = { + domain = "dex.0x76.dev"; + port = 5556; + }; + o2p_proxy = { + domain = "o2p.0x76.dev"; + port = 8484; + }; + }; + }; + "WoolooTV" = { + ip = "10.42.42.13"; + mac = "74:40:be:48:85:a4"; + nix = false; + }; + "outline" = { + ip = "10.42.42.14"; + mac = "52:13:EB:FD:87:F0"; + exposes.outline = { + domain = "outline.0x76.dev"; + port = 3000; + }; + }; + "dns-1" = { + profile = "dns"; + ip = "10.42.42.15"; + mac = "5E:F6:36:23:16:E3"; + tags = [ "dns" "networking" ]; + }; + "dns-2" = { + profile = "dns"; + ip = "10.42.42.16"; + mac = "B6:04:0B:CD:0F:9F"; + tags = [ "dns" "networking" ]; + }; + "minio" = { + ip = "10.42.42.17"; + mac = "0A:06:5E:E7:9A:0C"; + exposes.minio = { + domain = "o.0x76.dev"; + port = 9000; + }; + }; + "mailserver" = { + ip = "10.42.42.18"; + mac = "AA:F2:3D:5E:B3:40"; + }; + "victoriametrics" = { + ip = "10.42.42.19"; + mac = "9E:91:61:35:84:1F"; + exposes = { + grafana = { + domain = "grafana.0x76.dev"; + port = 2342; + }; + }; + }; + "unifi" = { + ip = "10.42.42.20"; + mac = "1A:88:A0:B0:65:B4"; + }; + "minecraft" = { + ip = "10.42.42.21"; + mac = "EA:30:73:E4:B6:69"; + nix = false; + }; + "gitea" = { + ip = "10.42.42.22"; + mac = "DE:5F:B0:83:6F:34"; + exposes.git = { + domain = "git.0x76.dev"; + port = 3000; + }; + }; + "hedgedoc" = { + ip = "10.42.42.23"; + mac = "86:BC:0C:18:BC:9B"; + exposes.md = { + domain = "md.0x76.dev"; + port = 3000; + }; + }; + "zmeura" = { + ip = "10.42.42.24"; + mac = "b8:27:eb:d5:e0:f5"; + nix = false; + exposes.andreea = { + domain = "andreea.redshifts.xyz"; + port = 8008; + }; + }; + "wireguard" = { + ip = "10.42.42.25"; + mac = "1E:ED:97:2C:C3:9D"; + }; + "grist" = { + ip = "10.42.42.26"; + mac = "B2:AA:AB:5D:2F:22"; + exposes.grist = { + domain = "grist.0x76.dev"; + port = 8484; + }; + }; + "bookwyrm" = { + ip = "10.42.42.27"; + mac = "9E:8A:6C:39:27:DE"; + nix = false; + exposes.books = { + domain = "books.meowy.tech"; + port = 8001; + }; + }; + "synapse" = { + ip = "10.42.42.28"; + mac = "9E:86:D3:46:EE:AE"; + }; + # 10.42.42.29 + "vault-1" = { + ip = "10.42.42.30"; + mac = "26:69:0E:7C:B3:79"; + profile = "vault-1"; + tags = [ "vault" ]; + }; + "vaultwarden" = { + ip = "10.42.42.31"; + mac = "96:61:03:16:63:98"; + }; + "ntfy" = { + ip = "10.42.42.32"; + mac = "7A:17:9E:80:72:01"; + exposes.ntfy.domain = "ntfy.0x76.dev"; + }; + "ci" = { + ip = "10.42.42.33"; + mac = "1E:24:DA:DB:4A:1A"; + }; + "nuc" = { + ip = "10.42.42.42"; + ip6 = "2001:41f0:9639:1::42"; + mac = "1C:69:7A:62:30:88"; + nix = false; + }; + "shield" = { + ip = "10.42.42.43"; + ip6 = "2001:41f0:9639:1::43"; + mac = "48:b0:2d:4e:29:c0"; + nix = false; + }; + "eevee" = { + ip = "10.42.42.69"; + ip6 = "2001:41f0:9639:1:a83:e416:dc99:5ed3"; + mac = "34:97:f6:93:9A:AA"; + type = "local"; + }; +} diff --git a/nixos/hosts/olympus/dex/configuration.nix b/nixos/hosts/olympus/dex/configuration.nix new file mode 100644 index 00000000..2ca6d0ef --- /dev/null +++ b/nixos/hosts/olympus/dex/configuration.nix @@ -0,0 +1,106 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ config, pkgs, ... }: +let + vs = config.vault-secrets.secrets; + db_user = "dex"; + db_name = "dex"; + inherit (config.meta.exposes.dex) port; + metricsPort = 5558; +in { + imports = [ ]; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "23.05"; # Did you read the comment? + + networking.firewall.allowedTCPPorts = [ port metricsPort ]; + + vault-secrets.secrets.dex = { }; + vault-secrets.secrets.oauth2_proxy = { }; + + services = { + + postgresql = { + enable = true; + package = pkgs.postgresql_15; + ensureDatabases = [ db_name ]; + ensureUsers = [{ + name = db_user; + ensurePermissions = { + "DATABASE ${db_name}" = "ALL PRIVILEGES"; + "schema public" = "ALL"; + }; + }]; + }; + + dex = { + enable = true; + settings = { + issuer = "https://dex.0x76.dev"; + storage = { + type = "postgres"; + config = { + host = "/var/run/postgresql"; + user = db_user; + database = db_name; + }; + }; + web.http = "0.0.0.0:${toString port}"; + telemetry.http = "0.0.0.0:${toString metricsPort}"; + connectors = [{ + type = "gitea"; + id = "gitea"; + name = "Gitea"; + config = { + clientID = "$GITEA_CLIENT_ID"; + clientSecret = "$GITEA_CLIENT_SECRET"; + redirectURI = "https://dex.0x76.dev/callback"; + baseURL = "https://git.0x76.dev"; + }; + }]; + + staticClients = [ + { + id = "outline"; + name = "Outline"; + redirectURIs = [ "https://outline.0x76.dev/auth/oidc.callback" ]; + secretEnv = "OUTLINE_CLIENT_SECRET"; + } + { + id = "grafana"; + name = "Grafana"; + redirectURIs = [ "https://grafana.0x76.dev/login/generic_oauth" ]; + secretEnv = "GRAFANA_CLIENT_SECRET"; + } + { + id = "hedgedoc"; + name = "Hedgedoc"; + redirectURIs = [ "https://md.0x76.dev/auth/oauth2/callback" ]; + secretEnv = "HEDGEDOC_CLIENT_SECRET"; + } + { + id = "flux"; + name = "Weave Gitops Flux Dashboard"; + redirectURIs = [ "https://flux.0x76.dev/oauth2/callback" ]; + secretEnv = "FLUX_CLIENT_SECRET"; + } + { + id = "grist"; + name = "grist"; + redirectURIs = [ "https://grist.0x76.dev/oauth2/callback" ]; + secretEnv = "GRIST_CLIENT_SECRET"; + } + ]; + }; + + environmentFile = "${vs.dex}/environment"; + }; + }; +} diff --git a/nixos/hosts/olympus/dhcp/configuration.nix b/nixos/hosts/olympus/dhcp/configuration.nix new file mode 100644 index 00000000..0503693b --- /dev/null +++ b/nixos/hosts/olympus/dhcp/configuration.nix @@ -0,0 +1,102 @@ +{ config, flat_hosts, ... }: +let + inherit (builtins) filter hasAttr; + hostToKea = { hostname, mac, ip, ... }: { + inherit hostname; + hw-address = mac; + ip-address = ip; + }; + localDomain = config.networking.domain; + hosts = + filter (h: hasAttr "ip" h && hasAttr "mac" h && h.realm == localDomain) + flat_hosts; +in +{ + networking = { + defaultGateway = "10.42.42.1"; + nameservers = [ "10.42.42.15" "10.42.42.16" ]; + interfaces.eth0 = { + useDHCP = false; # It turns out the barber just doesn't shave + ipv4.addresses = [{ + address = "10.42.42.3"; + prefixLength = 23; + }]; + }; + }; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "21.11"; # Did you read the comment? + + networking.firewall.allowedUDPPorts = [ 67 ]; + + # services.prometheus.exporters.kea = { + # enable = true; + # openFirewall = true; + # controlSocketPaths = [ "/run/kea/kea-dhcp4.socket" ]; + # }; + + services.kea.dhcp4 = { + enable = true; + settings = { + authoritative = true; + valid-lifetime = 4000; + rebind-timer = 2000; + renew-timer = 1000; + + interfaces-config.interfaces = [ "eth0" ]; + + # control-socket = { + # socket-type = "unix"; + # socket-name = "/run/kea/kea-dhcp4.socket"; + # }; + # failed to initialize Kea server: configuration error using file '/etc/kea/dhcp4-server.conf': cannot create socket lockfile, /run/kea/kea-dhcp4.socket.lock, : No such file or directory + + lease-database = { + name = "/var/lib/kea/dhcp4.leases"; + persist = true; + type = "memfile"; + }; + + option-data = [ + { + name = "subnet-mask"; + data = "255.255.254.0"; + } + { + name = "broadcast-address"; + data = "10.42.43.255"; + } + { + name = "routers"; + data = "10.42.42.1"; + } + { + name = "domain-name-servers"; + data = "10.42.42.15, 10.42.42.16"; + } + { + name = "domain-name"; + data = localDomain; + } + { + name = "domain-search"; + data = localDomain; + } + ]; + + host-reservation-identifiers = [ "hw-address" ]; + + subnet4 = [{ + id = 1; + pools = [{ pool = "10.42.43.1 - 10.42.43.254"; }]; + subnet = "10.42.42.0/23"; + reservations = map hostToKea hosts; + }]; + }; + }; +} diff --git a/nixos/hosts/olympus/dns/configuration.nix b/nixos/hosts/olympus/dns/configuration.nix new file mode 100644 index 00000000..905aaf12 --- /dev/null +++ b/nixos/hosts/olympus/dns/configuration.nix @@ -0,0 +1,20 @@ +{ pkgs, ... }: { + imports = [ ]; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "21.11"; # Did you read the comment? + + # Additional packages + environment.systemPackages = with pkgs; [ dig dogdns ]; + + services.v.dns = { + enable = true; + openFirewall = true; + mode = "server"; + }; +} diff --git a/nixos/hosts/olympus/eevee/configuration.nix b/nixos/hosts/olympus/eevee/configuration.nix new file mode 100644 index 00000000..6e4e1710 --- /dev/null +++ b/nixos/hosts/olympus/eevee/configuration.nix @@ -0,0 +1,53 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ pkgs, ... }: { + imports = [ ./hardware-configuration.nix ./hardware.nix ]; + + # Bootloader. + boot = { + kernelPackages = pkgs.linuxPackages_latest; + initrd = { + kernelModules = [ "nvidia" "nvidia_modeset" "nvidia_uvm" "nvidia_drm" ]; + }; + loader.systemd-boot.configurationLimit = 5; + }; + + fileSystems."/".options = [ "compress=zstd" ]; + + # Set your time zone. + time.timeZone = "Europe/Amsterdam"; + + # Select internationalisation properties. + i18n.defaultLocale = "en_GB.UTF-8"; + i18n.extraLocaleSettings = { + LC_ADDRESS = "nl_NL.UTF-8"; + LC_IDENTIFICATION = "nl_NL.UTF-8"; + LC_MEASUREMENT = "nl_NL.UTF-8"; + LC_MONETARY = "nl_NL.UTF-8"; + LC_NAME = "nl_NL.UTF-8"; + LC_NUMERIC = "nl_NL.UTF-8"; + LC_PAPER = "nl_NL.UTF-8"; + LC_TELEPHONE = "nl_NL.UTF-8"; + LC_TIME = "nl_NL.UTF-8"; + }; + + # Enable CUPS to print documents. + services.printing.enable = true; + + environment.systemPackages = with pkgs; [ wireguard-tools ]; + + environment.sessionVariables.NIXOS_OZONE_WL = "1"; + + home-manager = { + users.vivian = import ./home; + }; + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "23.05"; # Did you read the comment? +} diff --git a/nixos/hosts/olympus/eevee/hardware-configuration.nix b/nixos/hosts/olympus/eevee/hardware-configuration.nix new file mode 100644 index 00000000..efc77070 --- /dev/null +++ b/nixos/hosts/olympus/eevee/hardware-configuration.nix @@ -0,0 +1,42 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ config, lib, modulesPath, ... }: + +{ + imports = [ (modulesPath + "/installer/scan/not-detected.nix") ]; + boot = { + + initrd.availableKernelModules = + [ "xhci_pci" "ahci" "nvme" "usbhid" "usb_storage" "sd_mod" ]; + initrd.kernelModules = [ ]; + kernelModules = [ "kvm-intel" ]; + extraModulePackages = [ ]; + }; + + fileSystems."/" = { + device = "/dev/disk/by-uuid/947a98af-9a4e-4811-a2ca-9aa00b319e9c"; + fsType = "btrfs"; + options = [ "subvol=@" ]; + }; + + fileSystems."/boot/efi" = { + device = "/dev/disk/by-uuid/D883-F146"; + fsType = "vfat"; + }; + + swapDevices = + [{ device = "/dev/disk/by-uuid/a99402e1-6f2a-4c4b-b69f-aae2fd13ffc0"; }]; + + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces..useDHCP`. + networking.useDHCP = lib.mkDefault true; + # networking.interfaces.enp0s31f6.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + powerManagement.cpuFreqGovernor = lib.mkDefault "powersave"; + hardware.cpu.intel.updateMicrocode = + lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/nixos/hosts/olympus/eevee/hardware.nix b/nixos/hosts/olympus/eevee/hardware.nix new file mode 100644 index 00000000..cd1cb84d --- /dev/null +++ b/nixos/hosts/olympus/eevee/hardware.nix @@ -0,0 +1,48 @@ +{ pkgs, ... }: { + hardware = { + enableAllFirmware = true; + nvidia = { + # package = config.boot.kernelPackages.nvidiaPackages.stable; + + # Open drivers cause gdm to crash + # open = true; + + # nvidia-drm.modeset=1 + modesetting.enable = true; + powerManagement.enable = false; + }; + + # Hardware acceleration + opengl = { + enable = true; + + # Vulkan + driSupport = true; + driSupport32Bit = true; + }; + + logitech.wireless = { + enable = true; + enableGraphical = true; + }; + }; + services = { + + hardware.bolt.enable = true; + + xserver.videoDrivers = [ "nvidia" ]; + + # udev + udev.packages = with pkgs; [ + android-udev-rules + logitech-udev-rules + wooting-udev-rules + ]; + + # SSD Trim + fstrim.enable = true; + }; + + # FS + fileSystems."/".options = [ "compress=zstd" ]; +} diff --git a/nixos/hosts/olympus/eevee/home/.gitignore b/nixos/hosts/olympus/eevee/home/.gitignore new file mode 100644 index 00000000..3e0fc8e7 --- /dev/null +++ b/nixos/hosts/olympus/eevee/home/.gitignore @@ -0,0 +1 @@ +*dconf_dump* \ No newline at end of file diff --git a/nixos/hosts/olympus/eevee/home/default.nix b/nixos/hosts/olympus/eevee/home/default.nix new file mode 100644 index 00000000..bf2d078a --- /dev/null +++ b/nixos/hosts/olympus/eevee/home/default.nix @@ -0,0 +1,9 @@ +{ pkgs, ... }: { + dconf.settings."org/gnome/desktop/peripherals/mouse" = { + accel-profile = "flat"; + }; + + home.packages = with pkgs; [ + zoom-us + ]; +} diff --git a/nixos/hosts/olympus/gitea/configuration.nix b/nixos/hosts/olympus/gitea/configuration.nix new file mode 100644 index 00000000..fd471d38 --- /dev/null +++ b/nixos/hosts/olympus/gitea/configuration.nix @@ -0,0 +1,105 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ lib, config, pkgs, ... }: +let + vs = config.vault-secrets.secrets; + inherit (config.meta.exposes.git) port; +in +{ + imports = [ ]; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "21.11"; # Did you read the comment? + + # Additional packages + environment.systemPackages = with pkgs; [ ]; + + environment.noXlibs = lib.mkForce false; + + networking.firewall.allowedTCPPorts = [ port ]; + services = { + + openssh.startWhenNeeded = false; + + fail2ban = { + enable = true; + maxretry = 3; + }; + + gitea = { + enable = true; + package = pkgs.forgejo; + lfs.enable = true; + dump.type = "tar.gz"; + database.type = "postgres"; + mailerPasswordFile = "${vs.gitea}/mailPassword"; + + settings = { + default.WORK_PATH = "/var/lib/gitea"; + actions = { "ENABLED" = true; }; + repository = { + "ENABLE_PUSH_CREATE_USER" = true; + "DEFAULT_PUSH_CREATE_PRIVATE" = false; + }; + service = { + "DEFAULT_KEEP_EMAIL_PRIVATE" = true; + "DISABLE_REGISTRATION" = true; + }; + indexer = { + "REPO_INDEXER_ENABLED" = true; + "REPO_INDEXER_PATH" = "indexers/repos.bleve"; + "MAX_FILE_SIZE" = 1048576; + "REPO_INDEXER_EXCLUDE" = "node_modules/**"; + }; + ui = { + "THEMES" = "forgejo-auto,forgejo-light,forgejo-dark,auto,gitea,arc-green,agatheme"; + "DEFAULT_THEME" = "forgejo-auto"; + "USE_SERVICE_WORKER" = true; + }; + server = { + LANDING_PAGE = "explore"; + SSH_PORT = 42; + DOMAIN = "git.0x76.dev"; + ROOT_URL = "https://git.0x76.dev"; + HTTP_PORT = port; + }; + session = { + "PROVIDER" = "db"; + "COOKIE_SECURE" = true; + }; + mailer = { + "ENABLED" = true; + # "IS_TLS_ENABLED" = true; + # "HOST" = "mail.0x76.dev:465"; + "FROM" = "gitea@0x76.dev"; + # "MAILER_TYPE" = "smtp"; + "USER" = "gitea@0x76.dev"; + + # Below is prep for 1.18 + "PROTOCOL" = "smtps"; + "SMTP_ADDR" = "mail.0x76.dev"; + "SMTP_PORT" = 465; + }; + }; + }; + }; + + vault-secrets.secrets.gitea = { + user = "gitea"; + group = "gitea"; + }; + + system.activationScripts.gitea-theme = + let target_dir = "${config.services.gitea.stateDir}/custom/public/css/"; + in lib.stringAfter [ "var" ] '' + mkdir -p ${target_dir} + ln -sf ${pkgs.v.gitea-agatheme} "${target_dir}/theme-agatheme.css" + ''; +} diff --git a/nixos/hosts/olympus/grist/configuration.nix b/nixos/hosts/olympus/grist/configuration.nix new file mode 100644 index 00000000..d24eec63 --- /dev/null +++ b/nixos/hosts/olympus/grist/configuration.nix @@ -0,0 +1,57 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ config, pkgs, ... }: +let vs = config.vault-secrets.secrets; +in { + imports = [ ]; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "23.11"; # Did you read the comment? + networking.firewall.allowedTCPPorts = [ 8484 ]; + + environment.systemPackages = with pkgs; [ sqlite ]; + virtualisation = { + + podman.enable = true; + oci-containers.backend = "podman"; + + oci-containers.containers.grist = { + image = + "gristlabs/grist:1.1.8"; + environment = { + APP_HOME_URL = "https://grist.0x76.dev"; + GRIST_SUPPORT_ANON = "false"; + GRIST_FORCE_LOGIN = "true"; + GRIST_SINGLE_ORG = "xirion"; + GRIST_ORG_IN_PATH = "false"; + GRIST_DEFAULT_EMAIL = "v@0x76.dev"; # Defines admin user + GRIST_HIDE_UI_ELEMENTS = + "helpCenter,billing,templates,multiSite,multiAccounts"; + GRIST_TELEMETRY_LEVEL = "off"; + GRIST_WIDGET_LIST_URL = + "https://github.com/gristlabs/grist-widget/releases/download/latest/manifest.json"; + + # No Python 2 + PYTHON_VERSION = "3"; + PYTHON_VERSION_ON_CREATION = "3"; + + GRIST_OIDC_IDP_ISSUER = "https://dex.0x76.dev"; + }; + environmentFiles = [ "${vs.grist}/environment" ]; + ports = [ "8484:8484" ]; + volumes = [ "/var/lib/grist:/persist" ]; + }; + }; + + vault-secrets.secrets.grist = { + quoteEnvironmentValues = false; # Needed for docker + services = [ "podman-grist" ]; + }; +} diff --git a/nixos/hosts/olympus/hedgedoc/configuration.nix b/nixos/hosts/olympus/hedgedoc/configuration.nix new file mode 100644 index 00000000..4525e08a --- /dev/null +++ b/nixos/hosts/olympus/hedgedoc/configuration.nix @@ -0,0 +1,87 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ lib, config, pkgs, ... }: +let + db_name = "hedgedoc"; + db_user = "hedgedoc"; + inherit (config.meta.exposes.md) port; + vs = config.vault-secrets.secrets; +in +{ + imports = [ ]; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "21.11"; # Did you read the comment? + + environment.noXlibs = lib.mkForce false; + + networking.firewall.allowedTCPPorts = [ port ]; + + vault-secrets.secrets.hedgedoc = { }; + + services.postgresql = { + enable = true; + package = pkgs.postgresql_13; + ensureDatabases = [ db_name ]; + ensureUsers = [{ + name = db_user; + ensurePermissions = { "DATABASE ${db_name}" = "ALL PRIVILEGES"; }; + }]; + }; + + services.hedgedoc = { + enable = true; + environmentFile = "${vs.hedgedoc}/environment"; + settings = { + host = "0.0.0.0"; + inherit port; + sessionSecret = "$SESSION_SECRET"; + domain = "md.0x76.dev"; + protocolUseSSL = true; + hsts.enable = true; + allowOrigin = [ config.services.hedgedoc.settings.domain "hedgedoc" ]; + allowAnonymous = false; + allowEmailRegister = false; + allowAnonymousEdits = true; + allowFreeURL = true; + requireFreeURLAuthentication = true; + imageUploadType = "minio"; + db = { + dialect = "postgres"; + username = db_user; + database = db_name; + host = "/run/postgresql"; + }; + s3bucket = "hedgedoc"; + minio = { + secure = true; + endPoint = "o.0x76.dev"; + port = 443; + accessKey = "$MINIO_ACCESS_KEY"; + secretKey = "$MINIO_SECRET_KEY"; + }; + email = false; + oauth2 = + let url = "https://dex.0x76.dev"; + in { + providerName = "Dex"; + clientID = "hedgedoc"; + clientSecret = "$DEX_CLIENT_SECRET"; + scope = "openid email profile"; + authorizationURL = "${url}/auth"; + tokenURL = "${url}/token"; + userProfileURL = "${url}/userinfo"; + userProfileUsernameAttr = "preferred_username"; + userProfileDisplayNameAttr = "name"; + userProfileEmailAttr = "email"; + }; + }; + }; +} diff --git a/nixos/hosts/olympus/kubernetes/README.md b/nixos/hosts/olympus/kubernetes/README.md new file mode 100644 index 00000000..216bd4bc --- /dev/null +++ b/nixos/hosts/olympus/kubernetes/README.md @@ -0,0 +1,9 @@ +# Kubernetes NixOS LXC Container + +## Required proxmox config +```ini +lxc.apparmor.profile: unconfined +lxc.cgroup.devices.allow: a +lxc.cap.drop: +lxc.mount.auto: proc:rw sys:rw +``` diff --git a/nixos/hosts/olympus/kubernetes/configuration.nix b/nixos/hosts/olympus/kubernetes/configuration.nix new file mode 100644 index 00000000..fe5dd43a --- /dev/null +++ b/nixos/hosts/olympus/kubernetes/configuration.nix @@ -0,0 +1,22 @@ +{ pkgs, ... }: { + # packages for administration tasks + environment.systemPackages = with pkgs; [ kompose kubectl k9s k3s ]; + + services.k3s = { + enable = true; + role = "server"; + extraFlags = toString [ + # "--kubelet-arg=v=4" # Optionally add additional args to k3s + "--cluster-cidr 10.24.0.0/16" + ]; + }; + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "23.05"; # Did you read the comment? + + networking.firewall.enable = false; +} diff --git a/nixos/hosts/olympus/mailserver/configuration.nix b/nixos/hosts/olympus/mailserver/configuration.nix new file mode 100644 index 00000000..c434d166 --- /dev/null +++ b/nixos/hosts/olympus/mailserver/configuration.nix @@ -0,0 +1,151 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ config, pkgs, ... }: +let vs = config.vault-secrets.secrets; +in { + imports = [ ]; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "22.11"; # Did you read the comment? + + networking.firewall.allowedTCPPorts = [ 80 443 ]; + + # needed as the mailserver configures its down DNS resolver + networking.extraHosts = '' + 10.42.42.6 vault.olympus + ''; + + vault-secrets.secrets.mailserver = { services = [ "dovecot2" "postfix" ]; }; + + mailserver = { + enable = true; + fqdn = "mail.0x76.dev"; + domains = [ "0x76.dev" "meowy.tech" "xirion.net" ]; + certificateScheme = "acme-nginx"; + enableManageSieve = true; + + monitoring = { + alertAddress = "v@0x76.dev"; + enable = true; + }; + + forwards = { + "thijmen@xirion.net" = "Thijmen@nouwens-lindemans.nl"; + }; + + loginAccounts = { + # People + "v@0x76.dev" = { + hashedPasswordFile = "${vs.mailserver}/v@0x76.dev"; + catchAll = [ "xirion.net" "0x76.dev" ]; + aliases = [ + "postmaster@0x76.dev" + "abuse@0x76.dev" + + "v@meowy.tech" + "abuse@meowy.tech" + "postmaster@meowy.tech" + + "@xirion.net" + "@0x76.dev" + ]; + }; + "laura@meowy.tech" = { + hashedPasswordFile = "${vs.mailserver}/laura@meowy.tech"; + aliases = [ "lau@meowy.tech" ]; + }; + + # Services + "gitea@0x76.dev" = { + hashedPasswordFile = "${vs.mailserver}/gitea@0x76.dev"; + sendOnly = true; + }; + "matrix@meowy.tech" = { + hashedPasswordFile = "${vs.mailserver}/matrix@meowy.tech"; + sendOnly = true; + }; + "outline@0x76.dev" = { + hashedPasswordFile = "${vs.mailserver}/outline@0x76.dev"; + sendOnly = true; + }; + "vaultwarden@0x76.dev" = { + hashedPasswordFile = "${vs.mailserver}/vaultwarden@0x76.dev"; + sendOnly = true; + }; + "snapraid@0x76.dev" = { + hashedPasswordFile = "${vs.mailserver}/snapraid@0x76.dev"; + sendOnly = true; + }; + "mastodon@xirion.net" = { + hashedPasswordFile = "${vs.mailserver}/mastodon@xirion.net"; + sendOnly = true; + }; + }; + + indexDir = "/var/lib/dovecot/indices"; + fullTextSearch = { + enable = true; + # index new email as they arrive + autoIndex = true; + # this only applies to plain text attachments, binary attachments are never indexed + indexAttachments = true; + enforced = "body"; + memoryLimit = 2000; + autoIndexExclude = [ "\\Junk" ]; + }; + }; + services = { + + postfix.relayHost = "smtp.ziggozakelijk.nl"; + postfix.relayPort = 587; + + roundcube = { + enable = true; + package = pkgs.roundcube.withPlugins + (plugins: [ plugins.persistent_login pkgs.v.roundcube-swipe ]); + plugins = [ + "archive" + "managesieve" + "swipe" + # "enigma" + # "markasjunk" + "persistent_login" + ]; + # this is the url of the vhost, not necessarily the same as the fqdn of + # the mailserver + hostName = "webmail.0x76.dev"; + extraConfig = '' + # starttls needed for authentication, so the fqdn required to match + # the certificate + $config['smtp_host'] = "tls://${config.mailserver.fqdn}"; + $config['smtp_user'] = "%u"; + $config['smtp_pass'] = "%p"; + + $config['swipe_actions'] = [ + 'messagelist' => [ + 'left' => 'archive', + 'right' => 'archive', + 'down' => 'none' + ], + 'contactlist' => [ + 'left' => 'none', + 'right' => 'none', + 'down' => 'none' + ] + ]; + ''; + }; + + nginx = { enable = true; }; + }; + + security.acme.acceptTerms = true; + security.acme.defaults.email = "v@0x76.dev"; +} diff --git a/nixos/hosts/olympus/minecraft/configuration.nix b/nixos/hosts/olympus/minecraft/configuration.nix new file mode 100644 index 00000000..d052e3c7 --- /dev/null +++ b/nixos/hosts/olympus/minecraft/configuration.nix @@ -0,0 +1,44 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ lib, pkgs, ... }: { + imports = [ ]; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "21.11"; # Did you read the comment? + + # Additional packages + environment.systemPackages = with pkgs; [ ]; + + environment.noXlibs = lib.mkForce false; + + networking.firewall.allowedTCPPorts = [ ]; + + services.minecraft-server = { + enable = false; + package = pkgs.minecraftServers.purpur_1_18; + jvmOpts = "--add-modules=jdk.incubator.vector -Xmx2048M -Xms2048M"; + + declarative = true; + eula = true; + openFirewall = true; + serverProperties = { + server-port = 25565; + motd = "blahaj minecraft server!"; + white-list = true; + enable-rcon = true; + "timings.enabled" = false; + }; + whitelist = { + "0x76" = "5513404a-81a2-4c84-b952-18661b1803e7"; + red_shifts = "e0afdee5-e776-49a9-a0cd-c8753faf4255"; + iampilot = "4055515e-0567-4610-972e-8e530a5a9ccb"; + }; + }; +} diff --git a/nixos/hosts/olympus/minio/configuration.nix b/nixos/hosts/olympus/minio/configuration.nix new file mode 100644 index 00000000..1e4ffb86 --- /dev/null +++ b/nixos/hosts/olympus/minio/configuration.nix @@ -0,0 +1,48 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ config, pkgs, ... }: +let + vs = config.vault-secrets.secrets; + listenPort = config.meta.exposes.minio.port; + consolePort = listenPort + 1; +in +{ + imports = [ ]; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "21.11"; # Did you read the comment? + + # Additional packages + environment.systemPackages = with pkgs; [ ]; + + networking.firewall.allowedTCPPorts = [ listenPort consolePort ]; + + vault-secrets.secrets.minio = { }; + + services.minio = { + enable = true; + package = pkgs.minio_legacy_fs; + rootCredentialsFile = "${vs.minio}/environment"; + listenAddress = ":${toString listenPort}"; + consoleAddress = ":${toString consolePort}"; + }; + + # services.garage = { + # enable = true; + # replication_mode = "1"; + # package = pkgs.garage_0_8; + # settings = { + # s3_api = { + # api_bind_addr = "0.0.0.0:3900"; + # s3_region = "olympus"; + # }; + # }; + # }; +} diff --git a/nixos/hosts/olympus/mosquitto/configuration.nix b/nixos/hosts/olympus/mosquitto/configuration.nix new file mode 100644 index 00000000..56cb9b65 --- /dev/null +++ b/nixos/hosts/olympus/mosquitto/configuration.nix @@ -0,0 +1,56 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ config, pkgs, ... }: +let mosquittoPort = 1883; +in { + imports = [ ]; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "21.05"; # Did you read the comment? + + # Additional packages + environment.systemPackages = with pkgs; [ ]; + + services.mosquitto = { + enable = true; + listeners = [{ + port = mosquittoPort; + settings.allow_anonymous = true; + acl = [ "topic readwrite #" ]; + users = { + vivian = { acl = [ "readwrite #" ]; }; + zigbee2mqtt = { acl = [ "readwrite #" ]; }; + }; + }]; + + }; + + services.zigbee2mqtt = { + enable = true; + dataDir = "/var/lib/zigbee2mqtt"; + settings = { + homeassistant = true; + permit_join = false; + + serial = { port = "/dev/ttyUSB0"; }; + + mqtt = { + base_topic = "zigbee2mqtt"; + server = "mqtt://localhost:${toString mosquittoPort}"; + user = "zigbee2mqtt"; + }; + + frontend = { port = 8080; }; + }; + }; + + networking.firewall.allowedTCPPorts = + [ mosquittoPort config.services.zigbee2mqtt.settings.frontend.port ]; +} diff --git a/nixos/hosts/olympus/nginx/configuration.nix b/nixos/hosts/olympus/nginx/configuration.nix new file mode 100644 index 00000000..8746cee7 --- /dev/null +++ b/nixos/hosts/olympus/nginx/configuration.nix @@ -0,0 +1,151 @@ +{ pkgs, ... }: +let + clientConfig = { + "m.homeserver" = { + base_url = "https://chat.meowy.tech"; + server_name = "meowy.tech"; + }; + "m.identity_server" = { }; + }; + serverConfig."m.server" = "chat.meowy.tech:443"; + mkWellKnown = data: '' + add_header Content-Type application/json; + add_header Access-Control-Allow-Origin *; + return 200 '${builtins.toJSON data}'; + ''; +in +{ + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "21.05"; # Did you read the comment? + + networking.firewall.allowedTCPPorts = [ 80 443 ]; + services = { + + # Generates vhosts for all hosts that have an `exposes` section + v.nginx.autoExpose = true; + + nginx = { + enable = true; + statusPage = true; + recommendedProxySettings = true; + recommendedTlsSettings = true; + recommendedOptimisation = true; + recommendedBrotliSettings = true; + clientMaxBodySize = "500m"; + + package = pkgs.nginxMainline; + + # Templated + virtualHosts = { + "pass.0x76.dev" = { + enableACME = true; + forceSSL = true; + locations = { + + "/".proxyPass = "http://vaultwarden.olympus:8222"; + "/".proxyWebsockets = true; + + "/notifications/hub/negotiate" = { + proxyPass = "http://vaultwarden.olympus:8222"; + proxyWebsockets = true; + }; + "/notifications/hub" = { + proxyPass = "http://vaultwarden.olympus:3012"; + proxyWebsockets = true; + }; + }; + }; + + # Meow + "meowy.tech" = { + enableACME = true; + forceSSL = true; + locations = { + "/".extraConfig = '' + add_header Content-Type 'text/html; charset=UTF-8'; + return 200 '

meow

'; + ''; + "= /.well-known/matrix/client".extraConfig = + mkWellKnown clientConfig; + "= /.well-known/matrix/server".extraConfig = + mkWellKnown serverConfig; + }; + }; + "chat.meowy.tech" = { + enableACME = true; + forceSSL = true; + locations = { + "/".extraConfig = '' + return 307 https://element.chat.meowy.tech; + ''; + "/_matrix".proxyPass = "http://synapse.olympus:8008"; + "/_synapse/client".proxyPass = "http://synapse.olympus:8008"; + "/_synapse/admin" = { + # Allow only local and my own IPs + extraConfig = '' + allow 127.0.0.1; + allow 10.42.42.0/23; + allow 192.168.0.0/23; + allow 80.60.83.220; + allow 83.128.154.23; + allow 62.45.26.248; + allow 195.85.167.32/29; + deny all; + ''; + proxyPass = "http://synapse.olympus:8008"; + }; + }; + }; + "element.chat.meowy.tech" = { + enableACME = true; + forceSSL = true; + + root = pkgs.element-web.override { + conf = { + default_server_config = clientConfig; + show_labs_settings = true; + brand = "chat.meowy.tech"; + }; + }; + }; + "cinny.chat.meowy.tech" = { + enableACME = true; + forceSSL = true; + + root = pkgs.cinny.override { + conf = { + defaultHomeserver = 0; + allowCustomHomeservers = false; + homeserverList = [ "chat.meowy.tech" ]; + }; + }; + }; + "admin.chat.meowy.tech" = { + enableACME = true; + forceSSL = true; + root = pkgs.synapse-admin; + }; + }; + }; + + prometheus.exporters = { + nginx = { + enable = true; + openFirewall = true; + }; + }; + }; + security = { + acme = { + + defaults.email = "vivian@0x76.dev"; + acceptTerms = true; + preliminarySelfsigned = true; + }; + }; +} diff --git a/nixos/hosts/olympus/ntfy/configuration.nix b/nixos/hosts/olympus/ntfy/configuration.nix new file mode 100644 index 00000000..a20b8d2d --- /dev/null +++ b/nixos/hosts/olympus/ntfy/configuration.nix @@ -0,0 +1,38 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ pkgs, ... }: + +{ + imports = [ ]; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "22.11"; # Did you read the comment? + + # Additional packages + environment.systemPackages = with pkgs; [ ntfy-sh ]; + + networking.firewall.allowedTCPPorts = [ 80 9090 ]; + + services.ntfy-sh = + let datadir = "/var/lib/ntfy-sh"; + in { + enable = true; + settings = { + base-url = "https://ntfy.0x76.dev"; + listen-http = ":80"; + cache-file = "${datadir}/cache.db"; + auth-file = "${datadir}/user.db"; + auth-default-access = "deny-all"; + behind-proxy = true; + attachment-cache-dir = "${datadir}/attachments"; + metrics-listen-http = ":9090"; + }; + }; +} diff --git a/nixos/hosts/olympus/outline/configuration.nix b/nixos/hosts/olympus/outline/configuration.nix new file mode 100644 index 00000000..7db54e9a --- /dev/null +++ b/nixos/hosts/olympus/outline/configuration.nix @@ -0,0 +1,63 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ config, ... }: +let + vs = config.vault-secrets.secrets; + inherit (config.meta.exposes.outline) port; +in +{ + imports = [ ]; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "22.11"; # Did you read the comment? + + # Additional packages + networking.firewall.allowedTCPPorts = [ port ]; + + vault-secrets.secrets.outline = { + inherit (config.services.outline) user group; + }; + + services.outline = { + inherit port; + + enable = true; + concurrency = 1; + redisUrl = "local"; + databaseUrl = "local"; + publicUrl = "https://outline.0x76.dev"; + utilsSecretFile = "${vs.outline}/utilsSecret"; + secretKeyFile = "${vs.outline}/secretKey"; + storage = { + accessKey = "outline"; + secretKeyFile = "${vs.outline}/s3key"; + uploadBucketUrl = "https://o.0x76.dev"; + uploadBucketName = "outline"; + region = "us-east-1"; # fake + }; + oidcAuthentication = { + displayName = "Dex"; + userinfoUrl = "https://dex.0x76.dev/userinfo"; + tokenUrl = "https://dex.0x76.dev/token"; + clientId = "outline"; + authUrl = "https://dex.0x76.dev/auth"; + clientSecretFile = "${vs.outline}/dexClientSecret"; + }; + smtp = rec { + username = "outline@0x76.dev"; + fromEmail = username; + replyEmail = username; + secure = true; + port = 465; + host = "mail.0x76.dev"; + passwordFile = "${vs.outline}/mailPassword"; + }; + }; +} diff --git a/nixos/hosts/olympus/synapse/configuration.nix b/nixos/hosts/olympus/synapse/configuration.nix new file mode 100644 index 00000000..c2a87081 --- /dev/null +++ b/nixos/hosts/olympus/synapse/configuration.nix @@ -0,0 +1,111 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ config, pkgs, ... }: +let + vs = config.vault-secrets.secrets; + port = 8008; + metricsPort = 9000; +in +{ + imports = [ ]; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "22.11"; # Did you read the comment? + + networking.firewall.allowedTCPPorts = [ port metricsPort ]; + + vault-secrets.secrets.synapse = { + user = "matrix-synapse"; + group = "matrix-synapse"; + services = [ "matrix-synapse" ]; + }; + + services.postgresql = { + enable = true; + initialScript = pkgs.writeText "synapse-init.sql" '' + CREATE ROLE "matrix-synapse" WITH LOGIN PASSWORD 'synapse'; + CREATE DATABASE "matrix-synapse" WITH OWNER "matrix-synapse" + TEMPLATE template0 + LC_COLLATE = "C" + LC_CTYPE = "C"; + ''; + }; + + services.matrix-synapse = { + enable = true; + withJemalloc = true; + + extraConfigFiles = [ + "${vs.synapse}/macaroon_secret_key" + "${vs.synapse}/registration_shared_secret" + "${vs.synapse}/form_secret" + "${vs.synapse}/turn_shared_secret" + "${vs.synapse}/email_password" # Also contains the rest of the email config + ]; + + settings = + let + log_file = pkgs.writeText "log.yml" '' + version: 1 + + formatters: + structured: + class: synapse.logging.TerseJsonFormatter + + handlers: + file: + class: logging.handlers.TimedRotatingFileHandler + formatter: structured + filename: /var/lib/matrix-synapse/synapse.log + when: midnight + backupCount: 3 # Does not include the current log file. + encoding: utf8 + + loggers: + synapse: + level: INFO + handlers: [file] + ''; + in + { + server_name = "meowy.tech"; + enable_registration = true; + public_baseurl = "https://chat.meowy.tech"; + enable_metrics = true; + max_upload_size = "100M"; + registration_requires_token = true; + media_retention = { remote_media_lifetime = "90d"; }; + log_config = "${log_file}"; + listeners = [ + { + inherit port; + bind_addresses = [ "0.0.0.0" ]; + type = "http"; + tls = false; + x_forwarded = true; + resources = [{ + names = [ "client" "federation" ]; + compress = true; + }]; + } + { + port = metricsPort; + bind_addresses = [ "0.0.0.0" ]; + type = "metrics"; + tls = false; + resources = [{ + names = [ "metrics" ]; + compress = false; + }]; + } + ]; + }; + }; +} diff --git a/nixos/hosts/olympus/unifi/configuration.nix b/nixos/hosts/olympus/unifi/configuration.nix new file mode 100644 index 00000000..d67b079d --- /dev/null +++ b/nixos/hosts/olympus/unifi/configuration.nix @@ -0,0 +1,28 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ pkgs, pkgs_stable, lib, ... }: + +{ + imports = [ ]; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "21.11"; # Did you read the comment? + + networking.firewall.allowedTCPPorts = [ 8443 ]; + + environment.noXlibs = lib.mkForce false; + + services.unifi = { + enable = true; + unifiPackage = pkgs.unifi; + mongodbPackage = pkgs_stable.mongodb-4_2; + openFirewall = true; + }; +} diff --git a/nixos/hosts/olympus/vault-0/configuration.nix b/nixos/hosts/olympus/vault-0/configuration.nix new file mode 100644 index 00000000..359751a9 --- /dev/null +++ b/nixos/hosts/olympus/vault-0/configuration.nix @@ -0,0 +1,23 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +_: { + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "21.05"; # Did you read the comment? + + # Vault + services.v.vault = { + enable = true; + openFirewall = true; + node_id = "olympus-1"; + + autoUnseal = true; + autoUnsealKeysFile = "/var/lib/vault-unseal/keys.json"; + }; +} diff --git a/nixos/hosts/olympus/vault-0/migrate.hcl b/nixos/hosts/olympus/vault-0/migrate.hcl new file mode 100644 index 00000000..4717ae02 --- /dev/null +++ b/nixos/hosts/olympus/vault-0/migrate.hcl @@ -0,0 +1,10 @@ +storage_source "file" { + path = "/var/lib/vault" +} + +storage_destination "raft" { + path = "/var/lib/vault-raft" + node_id = "olympus-1" +} + +cluster_addr = "http://vault.olympus:8201" diff --git a/nixos/hosts/olympus/vault-1/configuration.nix b/nixos/hosts/olympus/vault-1/configuration.nix new file mode 100644 index 00000000..51607df5 --- /dev/null +++ b/nixos/hosts/olympus/vault-1/configuration.nix @@ -0,0 +1,23 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +_: { + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "21.05"; # Did you read the comment? + + # Vault + services.v.vault = { + enable = true; + openFirewall = true; + node_id = "olympus-2"; + + autoUnseal = true; + autoUnsealKeysFile = "/var/lib/vault-unseal/keys.json"; + }; +} diff --git a/nixos/hosts/olympus/vaultwarden/configuration.nix b/nixos/hosts/olympus/vaultwarden/configuration.nix new file mode 100644 index 00000000..c3d89975 --- /dev/null +++ b/nixos/hosts/olympus/vaultwarden/configuration.nix @@ -0,0 +1,55 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ config, pkgs, ... }: +let + vs = config.vault-secrets.secrets; + cfg = config.services.vaultwarden.config; +in +{ + imports = [ ]; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "22.11"; # Did you read the comment? + + # Additional packages + environment.systemPackages = with pkgs; [ ]; + + networking.firewall.allowedTCPPorts = [ cfg.ROCKET_PORT cfg.WEBSOCKET_PORT ]; + + vault-secrets.secrets.vaultwarden = { + user = "vaultwarden"; + group = "vaultwarden"; + }; + + services.vaultwarden = { + enable = true; + dbBackend = "sqlite"; + environmentFile = "${vs.vaultwarden}/environment"; + config = { + DOMAIN = "https://pass.0x76.dev"; + SIGNUPS_ALLOWED = false; + ROCKET_ADDRESS = "0.0.0.0"; + ROCKET_PORT = 8222; + + WEBSOCKET_ENABLED = true; + WEBSOCKET_ADDRESS = "0.0.0.0"; + WEBSOCKET_PORT = 3012; + + SMTP_HOST = "mail.0x76.dev"; + SMTP_FROM = "vaultwarden@0x76.dev"; + SMTP_PORT = 465; + SMTP_SECURITY = "force_tls"; + SMTP_DEBUG = false; + + SIGNUPS_VERIFY = true; + SIGNUPS_DOMAINS_WHITELIST = "xirion.net,0x76.dev,meowy.tech"; + }; + }; +} diff --git a/nixos/hosts/olympus/victoriametrics/configuration.nix b/nixos/hosts/olympus/victoriametrics/configuration.nix new file mode 100644 index 00000000..f565f79a --- /dev/null +++ b/nixos/hosts/olympus/victoriametrics/configuration.nix @@ -0,0 +1,129 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ config, ... }: +let + vmPort = 8428; + grafanaDomain = config.meta.exposes.grafana.domain; + grafanaPort = config.meta.exposes.grafana.port; + vs = config.vault-secrets.secrets; +in +{ + imports = [ ]; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "21.11"; # Did you read the comment? + networking.firewall.allowedTCPPorts = [ vmPort grafanaPort ]; + networking.firewall.allowedUDPPorts = [ vmPort ]; + services = { + + victoriametrics = { + enable = true; + listenAddress = ":${toString vmPort}"; + # Data Retention period in months + retentionPeriod = 36; + }; + + vmagent = { + enable = true; + openFirewall = true; + prometheusConfig = { + global = { + scrape_interval = "1m"; + scrape_timeout = "30s"; + }; + scrape_configs = [ + { + job_name = "kea"; + static_configs = [{ + targets = [ "dhcp.olympus:9547" ]; + labels.app = "dhcp"; + }]; + } + { + job_name = "nginx"; + static_configs = [{ + targets = [ "nginx.olympus:9113" ]; + labels.app = "nginx"; + }]; + } + { + job_name = "synapse"; + static_configs = [{ + targets = [ "synapse.olympus:9000" ]; + labels.app = "synapse"; + }]; + } + { + job_name = "wireguard"; + static_configs = [{ + targets = [ "wireguard.olympus:9586" ]; + labels.app = "wireguard"; + }]; + } + { + job_name = "ntfy"; + static_configs = [{ + targets = [ "ntfy.olympus:9090" ]; + labels.app = "ntfy"; + }]; + } + { + job_name = "dex"; + static_configs = [{ + targets = [ "dex.olympus:5558" ]; + labels.app = "dex"; + }]; + } + { + job_name = "unbound"; + static_configs = [{ + targets = [ "dns-1.olympus:9167" "dns-2.olympus:9167" ]; + labels.app = "dns"; + }]; + } + ]; + }; + }; + + grafana = { + enable = true; + settings = { + server = { + domain = grafanaDomain; + root_url = "https://${grafanaDomain}"; + http_addr = "0.0.0.0"; + http_port = grafanaPort; + }; + security.admin_password = "$__file{${vs.grafana}/password}"; + + "auth.generic_oauth" = { + name = "Dex"; + icon = "signin"; + enabled = true; + allow_sign_up = true; + client_id = "grafana"; + client_secret = "$__file{${vs.grafana}/dex_client_secret}"; + scopes = toString [ "openid" "profile" "email" "groups" ]; + auth_url = "https://dex.0x76.dev/auth"; + token_url = "https://dex.0x76.dev/token"; + api_url = "https://dex.0x76.dev/userinfo"; + skip_org_role_sync = true; + auto_login = true; + }; + + }; + }; + }; + + vault-secrets.secrets.grafana = { + user = "grafana"; + group = "grafana"; + }; +} diff --git a/nixos/hosts/olympus/wireguard/configuration.nix b/nixos/hosts/olympus/wireguard/configuration.nix new file mode 100644 index 00000000..3e240290 --- /dev/null +++ b/nixos/hosts/olympus/wireguard/configuration.nix @@ -0,0 +1,87 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ lib, config, pkgs, ... }: +let vs = config.vault-secrets.secrets; +in { + imports = [ ]; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "21.11"; # Did you read the comment? + + # Additional packages + environment.systemPackages = with pkgs; [ wireguard-tools ]; + + environment.noXlibs = lib.mkForce false; + networking = { + + firewall.allowedUDPPorts = + [ config.networking.wireguard.interfaces.wg0.listenPort ]; + firewall.checkReversePath = false; + + nat = { + enable = true; + internalInterfaces = [ "wg0" "eth0" ]; + externalInterface = "eth0"; + }; + + wireguard.interfaces.wg0 = { + ips = [ "10.100.0.1/24" ]; + listenPort = 51821; + privateKeyFile = "${vs.wireguard}/privateKey"; + + peers = [ + { + # Phone + publicKey = "K+99mvSYs4urcclreQDLA1pekD4xtu/mpS2uVWw8Bws="; + allowedIPs = [ "10.100.0.2/32" ]; + } + { + # Laura's laptop + publicKey = "ZWIaDGrASlTkEK75j10VeGCvrIGfpk4GPobmqcYX2D0="; + allowedIPs = [ "10.100.0.3/32" ]; + } + { + # Old Laptop + publicKey = "L8myt2bcdja7M+i+9eatdQRW8relPUoZZ9lEKSLe+m8="; + allowedIPs = [ "10.100.0.4/32" ]; + } + { + # New Laptop + publicKey = "+Ms3xV6LxNZWTQk11zoz+AUIV2uds6A64Wz15JlR/Ak="; + allowedIPs = [ "10.100.0.6/32" ]; + } + { + # Aerdenhout + # Useful setup video for opnsense: https://www.youtube.com/watch?v=RoXHe5dqCM0 + # https://docs.opnsense.org/manual/how-tos/wireguard-s2s.html + publicKey = "KgqLhmUMX6kyTjRoa/GOCrZOvXNE5HWYuOr/T3v8/VI="; + allowedIPs = [ "10.100.0.5/32" "192.168.0.0/23" "10.10.10.0/24" ]; + endpoint = "62.45.26.248:51820"; + persistentKeepalive = 25; + } + ]; + }; + }; + + vault-secrets.secrets.wireguard = { + services = [ "wireguard-wg0" ]; + loginRetries = 25; + }; + + boot.kernel.sysctl = { + "net.ipv4.ip_forward" = 1; + "net.ipv6.conf.all.forwarding" = 1; + }; + + services.prometheus.exporters.wireguard = { + enable = true; + openFirewall = true; + }; +} diff --git a/nixos/hosts/thalassa/aoife/README.md b/nixos/hosts/thalassa/aoife/README.md new file mode 100644 index 00000000..6dee9969 --- /dev/null +++ b/nixos/hosts/thalassa/aoife/README.md @@ -0,0 +1,22 @@ +# Aoife +This is the NixOS config for my laptop `aoife`. + +## Hardware +This is a Thinkpad Z16 Gen 1. + +**CPU**: AMD Ryzen 9 PRO 6950H (16 cores) @ 4.935GHz + +**RAM**: 32GB LPDDR5 6400MHz + +**SCREEN**: 16" 3840 x 2400 OLED + +**GPU**: AMD Radeon™ RX 6500M, 4 GB, GDDR6 + + +## Software +**OS**: NixOS + +**DE**: Gnome + +**Shell**: ZSH (grml) + diff --git a/nixos/hosts/thalassa/aoife/configuration.nix b/nixos/hosts/thalassa/aoife/configuration.nix new file mode 100644 index 00000000..ddeb1fe8 --- /dev/null +++ b/nixos/hosts/thalassa/aoife/configuration.nix @@ -0,0 +1,44 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ inputs, lib, ... }: { + imports = [ + ./hardware-configuration.nix + inputs.nixos-hardware.nixosModules.lenovo-thinkpad-z + ./hardware.nix + ]; + + # Bootloader. + boot = { + bootspec.enable = true; + initrd.kernelModules = [ "amdgpu" ]; + resumeDevice = "/dev/nvme0n1p2"; + loader.systemd-boot.enable = lib.mkForce false; + + kernel.sysctl = { + "perf_event_paranoid" = 1; + "kptr_restrict" = 0; + }; + lanzaboote = { + enable = true; + configurationLimit = 5; + pkiBundle = "/etc/secureboot"; + }; + }; + + home-manager.users.vivian = import ./home; + + # Enable Ozone rendering for Chromium and Electron apps. + environment.sessionVariables.NIXOS_OZONE_WL = "1"; + + # environment.sessionVariables.INFRA_INFO = self; # hosts.${config.networking.domain}.${config.networking.hostName}; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "23.05"; # Did you read the comment? +} diff --git a/nixos/hosts/thalassa/aoife/hardware-configuration.nix b/nixos/hosts/thalassa/aoife/hardware-configuration.nix new file mode 100644 index 00000000..c6cd2ce2 --- /dev/null +++ b/nixos/hosts/thalassa/aoife/hardware-configuration.nix @@ -0,0 +1,42 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ config, lib, modulesPath, ... }: + +{ + imports = [ (modulesPath + "/installer/scan/not-detected.nix") ]; + boot = { + + initrd.availableKernelModules = + [ "nvme" "xhci_pci" "thunderbolt" "usb_storage" "sd_mod" "sdhci_pci" ]; + initrd.kernelModules = [ ]; + kernelModules = [ "kvm-amd" ]; + extraModulePackages = [ ]; + }; + + fileSystems."/" = { + device = "/dev/disk/by-uuid/c184866a-9a53-4a9f-9a1f-493792af7ea9"; + fsType = "btrfs"; + options = [ "subvol=@" ]; + }; + + fileSystems."/boot/efi" = { + device = "/dev/disk/by-uuid/5BB8-7503"; + fsType = "vfat"; + }; + + swapDevices = + [{ device = "/dev/disk/by-uuid/bedb5b75-578e-441f-a9eb-2ecff1f4cfca"; }]; + + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces..useDHCP`. + networking.useDHCP = lib.mkDefault true; + # networking.interfaces.wlp4s0.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.amd.updateMicrocode = + lib.mkDefault config.hardware.enableRedistributableFirmware; + # high-resolution display +} diff --git a/nixos/hosts/thalassa/aoife/hardware.nix b/nixos/hosts/thalassa/aoife/hardware.nix new file mode 100644 index 00000000..3c5becd6 --- /dev/null +++ b/nixos/hosts/thalassa/aoife/hardware.nix @@ -0,0 +1,55 @@ +{ pkgs, ... }: { + hardware = { + enableAllFirmware = true; + + bluetooth.enable = true; + + # Vulkan + opengl.driSupport = true; + opengl.extraPackages = with pkgs; [ + amdvlk + rocm-opencl-icd + rocm-opencl-runtime + ]; + }; + services = { + + hardware.bolt.enable = true; + + fprintd.enable = true; + + # Video Driver + xserver.videoDrivers = [ "amdgpu" ]; + xserver = { + dpi = 280; + xkbOptions = "caps:swapescape"; + }; + + # SSD Trim + fstrim.enable = true; + + # Power Management + upower.enable = true; + thermald.enable = true; + }; + + # hardware.trackpoint.enable = true; + + # FS + fileSystems."/".options = [ "compress=zstd" ]; + + powerManagement = { + enable = true; + powertop.enable = true; + }; + security = { + tpm2 = { + + # tpm + enable = true; + pkcs11.enable = true; # expose /run/current-system/sw/lib/libtpm2_pkcs11.so + tctiEnvironment.enable = true; + }; + }; # TPM2TOOLS_TCTI and TPM2_PKCS11_TCTI env variables + users.users.vivian.extraGroups = [ "tss" ]; # tss group has access to TPM devices +} diff --git a/nixos/hosts/thalassa/aoife/home/.gitignore b/nixos/hosts/thalassa/aoife/home/.gitignore new file mode 100644 index 00000000..3e0fc8e7 --- /dev/null +++ b/nixos/hosts/thalassa/aoife/home/.gitignore @@ -0,0 +1 @@ +*dconf_dump* \ No newline at end of file diff --git a/nixos/hosts/thalassa/aoife/home/default.nix b/nixos/hosts/thalassa/aoife/home/default.nix new file mode 100644 index 00000000..5c543197 --- /dev/null +++ b/nixos/hosts/thalassa/aoife/home/default.nix @@ -0,0 +1,16 @@ +{ pkgs, ... }: { + # Custom dconf settings + dconf.settings."org/gnome/desktop/input-sources" = { + xkb-options = [ "caps:swapescape" ]; + }; + + programs.zsh.envExtra = '' + source ~/.zshrc.secrets + ''; + + home.packages = with pkgs; [ + libreoffice-fresh + jetbrains.clion + jetbrains.rust-rover + ]; +} diff --git a/nixos/hosts/thalassa/default.nix b/nixos/hosts/thalassa/default.nix new file mode 100644 index 00000000..5b1e1db9 --- /dev/null +++ b/nixos/hosts/thalassa/default.nix @@ -0,0 +1,6 @@ +{ + "aoife" = { + type = "local"; + mac = "04:7b:cb:b6:2d:88"; + }; +} diff --git a/nixos/hosts/thalassa/null/README.md b/nixos/hosts/thalassa/null/README.md new file mode 100644 index 00000000..bd765da1 --- /dev/null +++ b/nixos/hosts/thalassa/null/README.md @@ -0,0 +1,10 @@ +# null +This folder contains the NixOS configuration for my laptop, with hostname `null`. + +## Information +* OS: NixOS +* WM: hyprland +* Terminal: foot +* Shell: zsh +* Theme: Captuccin Pink Dark +* Launcher: wofi diff --git a/nixos/hosts/thalassa/null/configuration.nix b/nixos/hosts/thalassa/null/configuration.nix new file mode 100644 index 00000000..143f5bfb --- /dev/null +++ b/nixos/hosts/thalassa/null/configuration.nix @@ -0,0 +1,267 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ pkgs, inputs, ... }: +let + nvidia-offload = pkgs.writeShellScriptBin "nvidia-offload" '' + export __NV_PRIME_RENDER_OFFLOAD=1 + export __NV_PRIME_RENDER_OFFLOAD_PROVIDER=NVIDIA-G0 + export __GLX_VENDOR_LIBRARY_NAME=nvidia + export __VK_LAYER_NV_optimus=NVIDIA_only + export LIBVA_DRIVER_NAME=nvidia + export GBM_BACKEND=nvidia-drm + + exec "$@" + ''; + run-hyprland = pkgs.writeShellScriptBin "run-hyprland" '' + export _JAVA_AWT_WM_NONREPARENTING=1 + export XCURSOR_SIZE=32 + + export CLUTTER_BACKEND=wayland + export XDG_SESSION_TYPE=wayland + export QT_WAYLAND_DISABLE_WINDOWDECORATION=1 + export MOZ_ENABLE_WAYLAND=1 + export WLR_NO_HARDWARE_CURSORS=1 + export WLR_BACKEND=vulkan + export QT_QPA_PLATFORM=wayland + export GDK_BACKEND=wayland + export SDL_VIDEODRIVER=wayland + + exec Hyprland + ''; +in +{ + imports = [ + # Include the results of the hardware scan. + ./hardware-configuration.nix + ./rescue-boot.nix + ./networking.nix + ]; + home-manager = { + + # home-manager + useGlobalPkgs = true; + useUserPackages = true; + users.vivian = import ./home; + extraSpecialArgs = { inherit inputs; }; + }; + security = { + + pam.services.swaylock = { }; + + sudo.wheelNeedsPassword = true; + rtkit.enable = true; + + # Enables logging in with my Solokey + pam.u2f = { + enable = true; + debug = false; + cue = true; + control = "sufficient"; + authFile = + "/etc/u2f-mappings"; # use `pamu2fcfg` from `pkgs.pam_u2f` to generate this config + }; + }; + + fonts = { + fonts = with pkgs; [ + material-design-icons + noto-fonts + noto-fonts-cjk + noto-fonts-emoji + dejavu_fonts + (nerdfonts.override { + fonts = + [ "DejaVuSansMono" "Ubuntu" "DroidSansMono" "NerdFontsSymbolsOnly" ]; + }) + ]; + + enableDefaultFonts = false; + + fontconfig = { + defaultFonts = { + monospace = [ "DejaVuSansMono Nerd Font" "Noto Color Emoji" ]; + sansSerif = + [ "DejaVu Sans" "DejaVuSansMono Nerd Font" "Noto Color Emoji" ]; + serif = + [ "DejaVu Serif" "DejaVuSansMono Nerd Font" "Noto Color Emoji" ]; + emoji = [ "Noto Color Emoji" ]; + }; + }; + }; + + # Bootloader. + # boot.initrd.systemd.enable = true; # Experimental + boot = { + kernelPackages = pkgs.linuxPackages_latest; + loader = { + systemd-boot.editor = false; + systemd-boot.enable = true; + # loader.systemd-boot.configurationLimit = 6; + efi.canTouchEfiVariables = true; + efi.efiSysMountPoint = "/boot/efi"; + }; + + kernel.sysctl = { "fs.inotify.max_user_watches" = 524288; }; + }; + services = { + + gnome.gnome-keyring.enable = true; + + udisks2.enable = true; + dbus.enable = true; + + xserver = { + enable = false; + layout = "us"; + xkbVariant = "altgr-intl"; + xkbOptions = "caps:swapescape"; + videoDrivers = [ "nvidia" ]; + }; + blueman.enable = true; + + # Enable CUPS to print documents. + printing.enable = true; + pipewire = { + enable = true; + alsa.enable = true; + alsa.support32Bit = true; + pulse.enable = true; + # If you want to use JACK applications, uncomment this + #jack.enable = true; + + # use the example session manager (no others are packaged yet so this is enabled by default, + # no need to redefine it in your config for now) + #media-session.enable = true; + }; + + fstrim.enable = true; + + # don't shutdown when power button is short-pressed + logind.extraConfig = '' + HandlePowerKey=suspend + ''; + + udev.packages = with pkgs; [ + android-udev-rules + logitech-udev-rules + wooting-udev-rules + ]; + }; + fileSystems = { + + "/".options = [ "compress=zstd" ]; + "/home".options = [ "compress=zstd" ]; + "/nix".options = [ "compress=zstd" "noatime" ]; + }; + i18n = { + + # Filesystem dedup + # services.beesd.filesystems = { + # root = { + # spec = "LABEL=nixos"; + # hashTableSizeMB = 256; + # verbosity = "crit"; + # extraOptions = [ "--loadavg-target" "2.0" ]; + # }; + # }; + + # Select internationalisation properties. + defaultLocale = "en_GB.utf8"; + + extraLocaleSettings = { + LC_ADDRESS = "nl_NL.UTF-8"; + LC_IDENTIFICATION = "nl_NL.UTF-8"; + LC_MEASUREMENT = "nl_NL.UTF-8"; + LC_MONETARY = "nl_NL.UTF-8"; + LC_NAME = "nl_NL.UTF-8"; + LC_NUMERIC = "nl_NL.UTF-8"; + LC_PAPER = "nl_NL.UTF-8"; + LC_TELEPHONE = "nl_NL.UTF-8"; + LC_TIME = "en_DK.UTF-8"; + }; + + supportedLocales = + [ "en_GB.UTF-8/UTF-8" "nl_NL.UTF-8/UTF-8" "en_DK.UTF-8/UTF-8" ]; + }; + + xdg.portal = { + enable = true; + wlr.enable = true; + }; + programs = { + + # Hyprland + hyprland = { + enable = true; + package = null; # Managed by home manager + }; + + steam = { + enable = true; + remotePlay.openFirewall = true; + dedicatedServer.openFirewall = true; + }; + + ssh.startAgent = true; + }; + + environment.loginShellInit = '' + if [ -z $DISPLAY ] && [ "$(tty)" = "/dev/tty1" ]; then + ${run-hyprland}/bin/run-hyprland + fi + ''; + hardware = { + + nvidia.prime = { + offload.enable = true; + intelBusId = "PCI:0:2:0"; + nvidiaBusId = "PCI:1:0:0"; + }; + + opengl = { + enable = true; + extraPackages = with pkgs; [ + vaapiVdpau + intel-media-driver # LIBVA_DRIVER_NAME=iHD + vaapiIntel # LIBVA_DRIVER_NAME=i965 (older but works better for Firefox/Chromium) + libvdpau-va-gl + ]; + }; + + bluetooth.enable = true; + + saleae-logic.enable = true; + pulseaudio.enable = false; + }; + + virtualisation.podman.enable = true; + + # Enable sound with pipewire. + sound.enable = true; + + environment.systemPackages = with pkgs; [ + pciutils + nvidia-offload + run-hyprland + wireguard-tools + slurp + gdb + + swaylock-effects # Has to be installed globally so that pam module works + ]; + + nix.extraOptions = '' + keep-outputs = true + keep-derivations = true + ''; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "22.05"; # Did you read the comment? +} diff --git a/nixos/hosts/thalassa/null/hardware-configuration.nix b/nixos/hosts/thalassa/null/hardware-configuration.nix new file mode 100644 index 00000000..4c230e9f --- /dev/null +++ b/nixos/hosts/thalassa/null/hardware-configuration.nix @@ -0,0 +1,56 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ config, lib, modulesPath, ... }: + +{ + imports = [ (modulesPath + "/installer/scan/not-detected.nix") ]; + boot = { + + initrd.availableKernelModules = + [ "xhci_pci" "ahci" "nvme" "rtsx_pci_sdmmc" ]; + initrd.kernelModules = [ ]; + kernelModules = [ "kvm-intel" ]; + extraModulePackages = [ ]; + }; + fileSystems = { + + "/" = { + device = "/dev/disk/by-uuid/d4f56e5b-2509-4e63-8324-65a35c71e90c"; + fsType = "btrfs"; + options = [ "subvol=@" ]; + }; + + "/nix" = { + device = "/dev/disk/by-uuid/d4f56e5b-2509-4e63-8324-65a35c71e90c"; + fsType = "btrfs"; + options = [ "subvol=@/nix" ]; + }; + + "/home" = { + device = "/dev/disk/by-uuid/d4f56e5b-2509-4e63-8324-65a35c71e90c"; + fsType = "btrfs"; + options = [ "subvol=@home" ]; + }; + + "/boot/efi" = { + device = "/dev/disk/by-uuid/D478-6F66"; + fsType = "vfat"; + }; + }; + + swapDevices = [ ]; + + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces..useDHCP`. + networking.useDHCP = lib.mkDefault true; + # networking.interfaces.wg0.useDHCP = lib.mkDefault true; + # networking.interfaces.wlp0s20f3.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + powerManagement.cpuFreqGovernor = lib.mkDefault "powersave"; + hardware.cpu.intel.updateMicrocode = + lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/nixos/hosts/thalassa/null/home/default.nix b/nixos/hosts/thalassa/null/home/default.nix new file mode 100644 index 00000000..b245deba --- /dev/null +++ b/nixos/hosts/thalassa/null/home/default.nix @@ -0,0 +1,207 @@ +{ config, pkgs, inputs, texlive, ... }: +let + tex = pkgs.texlive.combine { + inherit (pkgs.texlive) scheme-full; + dnd-5e-latex-template = { pkgs = [ pkgs.v.dnd-5e-latex-template ]; }; + }; +in +{ + programs = { + home-manager.enable = true; + + foot = { enable = true; }; + + nix-index.enable = true; + + exa = { + enable = true; + enableAliases = true; + }; + + bat.enable = true; + + git = { + enable = true; + package = pkgs.gitAndTools.gitFull; + userName = "0x76"; + userEmail = "v@0x76"; + lfs.enable = true; + # delta.enable = true; + extraConfig = { + push.autoSetupRemote = true; + init.defaultBranch = "main"; + }; + }; + + mako = { + enable = true; + extraConfig = '' + [mode=do-not-disturb] + invisible=1 + ''; + }; + + tmux = { + enable = true; + shortcut = "b"; + terminal = "screen-256color"; + clock24 = true; + }; + + firefox = { + enable = true; + package = pkgs.firefox-devedition-bin; + }; + + vscode = { + enable = true; + package = pkgs.vscode; + userSettings = { + "ltex.language" = "en-GB"; + "latex-workshop" = { + "linting.chktex.enabled" = true; + "latex.clean.subfolder.enabled" = true; + "latex.outDir" = "%TMPDIR%/%RELATIVE_DOC%"; + }; + "workbench.colorTheme" = "Catppuccin Frappé"; + "editor.fontFamily" = + "'DejaVuSansMono Nerd Font', 'monospace', monospace"; + "keyboard.dispatch" = "keyCode"; + "rust-analyzer.server.path" = "${pkgs.rust-analyzer}/bin/rust-analyzer"; + "terminal.integrated.defaultProfile.linux" = "zsh"; + "nix.enableLanguageServer" = true; # Enable LSP. + "nix.serverPath" = + "${pkgs.nil}/bin/nil"; # The path to the LSP server executable. + "[nix]" = { "editor.defaultFormatter" = "brettm12345.nixfmt-vscode"; }; + }; + extensions = with pkgs.vscode-extensions; + with pkgs.v.vscode-extensions; [ + # astro-build.astro-vscode + brettm12345.nixfmt-vscode + catppuccin.catppuccin-vsc + codezombiech.gitignore + editorconfig.editorconfig + foxundermoon.shell-format + james-yu.latex-workshop + jnoortheen.nix-ide + matklad.rust-analyzer + mkhl.direnv + ms-vscode-remote.remote-ssh + ms-vscode.cpptools + platformio.platformio-ide + redhat.vscode-yaml + tamasfe.even-better-toml + valentjn.vscode-ltex + vscodevim.vim + xaver.clang-format + ]; + }; + + direnv = { + enable = true; + nix-direnv = { enable = true; }; + }; + + zsh = { + enable = true; + sessionVariables = { DIRENV_LOG_FORMAT = ""; }; + }; + }; + home = { + username = "vivian"; + homeDirectory = "/home/vivian"; + stateVersion = "22.05"; + + packages = with pkgs; [ + appimage-run + brightnessctl + btop + calibre + cinny-desktop + discord-canary + fluxcd + fusee-launcher + gcc + gimp + gnome.eog + gnome.file-roller + gnome.gnome-font-viewer + gnome.nautilus + grim # Screenshot tool + inputs.comma.packages.${pkgs.system}.default + inputs.riff.packages.${pkgs.system}.riff + inputs.webcord.packages.${pkgs.system}.default + k9s + kubectl + libnotify + mullvad-vpn + neofetch + nixpkgs-review + nixfmt + ouch + plex-media-player + plexamp + python3 + retroarchFull + ripgrep + rsync + rustup + saleae-logic-2 + solo2-cli + steam-run + tex + thunderbird-wayland + v.deemix-gui + wf-recorder # Screenrecorder + wl-clipboard # Clipboard manager + wofi # Wayland rofi + wpa_supplicant_gui + ]; + }; + + imports = [ ./hyprland.nix ./neovim.nix ./eww ./theme.nix ]; + + xdg.mimeApps = { + enable = true; + defaultApplications = + let browser = [ "firefox.desktop" ]; + in { + "image/*" = "org.gnome.eog.desktop"; + "text/html" = browser; + "x-scheme-handler/http" = browser; + "x-scheme-handler/https" = browser; + "x-scheme-handler/ftp" = browser; + "x-scheme-handler/about" = browser; + "x-scheme-handler/unknown" = browser; + "application/x-extension-htm" = browser; + "application/x-extension-html" = browser; + "application/x-extension-shtml" = browser; + "application/xhtml+xml" = browser; + "application/x-extension-xhtml" = browser; + "application/x-extension-xht" = browser; + + "application/json" = browser; + "application/pdf" = browser; + + "x-scheme-handler/vscode" = "code-url-handler.desktop"; + "x-scheme-handler/discord" = "webcord.desktop"; + }; + }; + + xdg.userDirs = + let home = config.home.homeDirectory; + in { + enable = true; + createDirectories = true; + desktop = "${home}/.desktop"; + documents = "${home}/cloud/Documents"; + download = "${home}/dl"; + music = "${home}/cloud/Music"; + pictures = "${home}/cloud/Pictures"; + publicShare = "${home}/.publicShare"; + templates = "${home}/.templates"; + videos = "${home}/cloud/Videos"; + }; + + services.syncthing.enable = true; +} diff --git a/nixos/hosts/thalassa/null/home/eww/default.nix b/nixos/hosts/thalassa/null/home/eww/default.nix new file mode 100644 index 00000000..120b59a0 --- /dev/null +++ b/nixos/hosts/thalassa/null/home/eww/default.nix @@ -0,0 +1,42 @@ +{ pkgs, ... }: { + home = { + packages = with pkgs; [ + eww-wayland + pamixer + lua + (nerdfonts.override { fonts = [ "JetBrainsMono" ]; }) + ]; + file = { + + ".config/eww/eww.yuck".source = ./eww.yuck; + ".config/eww/eww.scss".text = builtins.readFile ./eww.scss; + + # scripts + # TODO: just link all scripts in ./scripts to .config/eww/scripts + ".config/eww/scripts/volume.sh" = { + source = ./scripts/volume.sh; + executable = true; + }; + + ".config/eww/scripts/wifi.sh" = { + source = ./scripts/wifi.sh; + executable = true; + }; + + ".config/eww/scripts/workspaces.sh" = { + source = ./scripts/workspaces.sh; + executable = true; + }; + + ".config/eww/scripts/workspaces.lua" = { + source = ./scripts/workspaces.lua; + executable = true; + }; + + ".config/eww/scripts/do-not-disturb.sh" = { + source = ./scripts/do-not-disturb.sh; + executable = true; + }; + }; + }; +} diff --git a/nixos/hosts/thalassa/null/home/eww/eww.scss b/nixos/hosts/thalassa/null/home/eww/eww.scss new file mode 100644 index 00000000..73435ed6 --- /dev/null +++ b/nixos/hosts/thalassa/null/home/eww/eww.scss @@ -0,0 +1,138 @@ +$light-gray: #9699b7; + +* { + all: unset; //Unsets everything so you can style everything from scratch + font-family: "JetBrainsMono" +} + +tooltip { + background-color: $base; + border-radius: 5px +} + +button { + transition: background-color 200ms, color 200ms; +} + +.active { + color: $pink; + font-size: 1.4rem; +} + +.inactive { + color: $base; + font-size: 1.4rem; +} + +.inactive:hover { + color: $light-gray; +} + +.bar { + background-color: $mantle; +} + +.clock { + font-weight: bold; + background-color: $base; + color: $text; + border-radius: 10px; + padding: 0.2rem; + margin: 0.5rem; +} + +.date { + font-size: 1.5rem; + color: $text; +} + + +.battery { + font-family: monospace; + font-size: 1.5rem; + color: $teal; +} + +.volume, +.dnd, +.wifi { + font-family: monospace; + font-size: 1.5rem; + color: $mauve; + padding: 0 5px; +} + + +// battery menu +.batterywindow { + background-color: $mantle; + border-radius: 5px; + font-size: 18px; + font-weight: normal; + color: $text; + + progressbar { + border-radius: 5px; + } + + progressbar progress { + background-color: $green; + } + + progressbar trough { + background-color: $base; + } + + .batterymenu { + padding: 10px; + } + +} + +// Calendar +.cal { + background-color: $mantle; + border-radius: 5px; + font-size: 18px; + font-weight: normal; + + .cal-in { + padding: 0px 10px 0px 10px; + color: $text; + + .cal { + &.highlight { + padding: 20px; + } + + padding: 5px 5px 5px 5px; + margin-left: 10px; + } + } +} + +calender { + color: $text; +} + +calendar:selected { + color: $mauve; +} + +calendar.header { + color: $overlay0; + font-weight: bold; +} + +calendar.button { + color: $base; +} + +calendar.highlight { + color: $overlay0; + font-weight: bold; +} + +calendar:indeterminate { + color: $text; +} \ No newline at end of file diff --git a/nixos/hosts/thalassa/null/home/eww/eww.yuck b/nixos/hosts/thalassa/null/home/eww/eww.yuck new file mode 100644 index 00000000..04673aff --- /dev/null +++ b/nixos/hosts/thalassa/null/home/eww/eww.yuck @@ -0,0 +1,164 @@ +(defwidget bar [] + (centerbox + :orientation "v" + (box + :valign "start" + :hexpand false + :vexpand false + :orientation "v" + :space-evenly false + ) + + (workspaces + :halign "center" + :vexpand true + :hexpand false + :orientation "v" + ) + + (box :valign "end" :hexpand false :vexpand true :orientation "v" :space-evenly false + (wifi) + (do-not-disturb) + (volume) + (battery) + (time) + ) + ) +) + +;; ━━━ BATTERY ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +(defwidget battery [] + (eventbox :onclick "eww open batterywindow --toggle" + (label + :text `${ + EWW_BATTERY.BAT0.status == "Charging" ? "" : + EWW_BATTERY.BAT0.capacity < 10 ? "" : + EWW_BATTERY.BAT0.capacity < 20 ? "" : + EWW_BATTERY.BAT0.capacity < 30 ? "" : + EWW_BATTERY.BAT0.capacity < 40 ? "" : + EWW_BATTERY.BAT0.capacity < 50 ? "" : + EWW_BATTERY.BAT0.capacity < 60 ? "" : + EWW_BATTERY.BAT0.capacity < 70 ? "" : + EWW_BATTERY.BAT0.capacity < 80 ? "" : + EWW_BATTERY.BAT0.capacity < 90 ? "" : "" + }` + :class "battery" + )) +) + +(defwidget batterymenu [] + (box :orientation "v" + :class "batterymenu" + (label :text "${EWW_BATTERY.BAT0.status}: ${EWW_BATTERY.BAT0.capacity}%") + (progress :value "${EWW_BATTERY.BAT0.capacity}" :orientation "h") ; TODO: change class (and color) on low juice + ) +) + +(defwindow batterywindow + :monitor 0 + :geometry (geometry + :x "53px" + :y "30px" + :anchor "bottom left" + ) + (batterymenu) +) + +; ━━━ do-not-disturb ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +(defvar dnd "") +(defwidget do-not-disturb [] + (eventbox + :orientation "h" + :halign "center" + :space-evenly false + :onclick "nohup ./scripts/do-not-disturb.sh &" + (label + :text {dnd} + :class "dnd" + ) + ) +) + +;; ━━━ WIFI ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +(defpoll wifi :interval "30s" "./scripts/wifi.sh") + +(defwidget wifi [] + (box + :orientation "h" + :halign "center" + :space-evenly false + (label + :text {wifi.icon} + :tooltip {wifi.status} + :class "wifi" + ) + ) +) + +;; ━━━ VOLUME ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +(defpoll volume :interval "1s" "./scripts/volume.sh") +(defwidget volume [] + (eventbox + :orientation "h" + :halign "center" + :space-evenly false + :onclick "pamixer -t" + (label + :text {volume.icon} + :tooltip "${volume.percent}%" + :class "volume" + ) + ) +) + +;; ━━━ TIME ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +(defpoll hour :interval "10s" "date +%H") +(defpoll minute :interval "10s" "date +%M") +(defpoll dateVar :interval "600s" "date '+%A %d.%m.%y'") + +(defwidget time [] + (eventbox + :cursor "hand" + :hexpand false + :vexpand false + :tooltip "${dateVar}" + :onclick "eww open calendar --toggle &" + (box :orientation "v" :hexpand false :vexpand false :space-evenly false :class "clock" + (label :class "date" :text "${hour}") + + (label :class "date" :text "${minute}") + ) + ) +) + +;; Calendar +(defpoll calendar_day :interval "20h" "date '+%d'") +(defpoll calendar_year :interval "20h" "date '+%Y'") +(defwidget cal [] + (box :class "cal" :orientation "v" + (box :class "cal-in" + (calendar :class "cal" + :day calendar_day + :year calendar_year)))) + +(defwindow calendar + :monitor 0 + :geometry (geometry :x "53px" + :y "5px" + :anchor "bottom left" + :width "270px" + :height "60px") + (cal)) + +(deflisten workspaces_listen "./scripts/workspaces.sh") +(defwidget workspaces [] + (literal :content workspaces_listen)) + +(defwindow bar + :monitor 0 + :exclusive false + :geometry (geometry :height "1080px" :x "-4px" :y "0px" + :width "52px" + :anchor "top left") + :stacking "fg" + (bar)) diff --git a/nixos/hosts/thalassa/null/home/eww/scripts/do-not-disturb.sh b/nixos/hosts/thalassa/null/home/eww/scripts/do-not-disturb.sh new file mode 100755 index 00000000..fe35e03c --- /dev/null +++ b/nixos/hosts/thalassa/null/home/eww/scripts/do-not-disturb.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env nix-shell +#! nix-shell -p jq -i bash + +if makoctl mode | rg -q "do-not-disturb"; then + eww update dnd="" + makoctl mode -r do-not-disturb > /dev/null +else + eww update dnd="" + makoctl mode -a do-not-disturb > /dev/null +fi diff --git a/nixos/hosts/thalassa/null/home/eww/scripts/volume.sh b/nixos/hosts/thalassa/null/home/eww/scripts/volume.sh new file mode 100755 index 00000000..f2746614 --- /dev/null +++ b/nixos/hosts/thalassa/null/home/eww/scripts/volume.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +per="$(pamixer --get-volume)" + +if pamixer --get-mute | rg -q true; then + icon="婢" +elif [ "$per" -gt 66 ]; then + icon="墳" # high +elif [ "$per" -gt 33 ]; then + icon="奔" # med +else + icon="奄" #low +fi + +printf "{\"icon\": \"${icon}\", \"percent\": \"${per}\"}" diff --git a/nixos/hosts/thalassa/null/home/eww/scripts/wifi.sh b/nixos/hosts/thalassa/null/home/eww/scripts/wifi.sh new file mode 100755 index 00000000..e3601ad0 --- /dev/null +++ b/nixos/hosts/thalassa/null/home/eww/scripts/wifi.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +if wpa_cli status | rg -q "wpa_state=COMPLETED"; then + icon="直" + status="Connected" +else + icon="睊" + status="offline" +fi + +printf "{\"icon\": \"${icon}\", \"status\": \"${status}\"}" diff --git a/nixos/hosts/thalassa/null/home/eww/scripts/workspaces.lua b/nixos/hosts/thalassa/null/home/eww/scripts/workspaces.lua new file mode 100755 index 00000000..43b14785 --- /dev/null +++ b/nixos/hosts/thalassa/null/home/eww/scripts/workspaces.lua @@ -0,0 +1,21 @@ +#!/usr/bin/env lua + +aw = io.popen("hyprctl monitors | grep active | sed 's/()/(1)/g' | sort | awk 'NR>1{print $1}' RS='(' FS=')'") +active_workspace = aw:read("*a") +aw:close() + +box = "(box :orientation \"v\" :spacing 1 :space-evenly \"true\" " + +for i = 1,10 do + if i == tonumber(active_workspace) then + local btn = "(button :class \"active\" :onclick \"hyprctl dispatch workspace "..i.." \" \"\")" + box = box .. btn + else + local btn = "(button :class \"inactive\" :onclick \"hyprctl dispatch workspace "..i.."\" \"\")" + box = box .. btn + end +end + +box = box .. ")" + +print(box) diff --git a/nixos/hosts/thalassa/null/home/eww/scripts/workspaces.sh b/nixos/hosts/thalassa/null/home/eww/scripts/workspaces.sh new file mode 100755 index 00000000..23cc9225 --- /dev/null +++ b/nixos/hosts/thalassa/null/home/eww/scripts/workspaces.sh @@ -0,0 +1,10 @@ +#!/bin/sh +workspaces() { + ./scripts/workspaces.lua +} + +workspaces + +tail -f /tmp/hypr/$HYPRLAND_INSTANCE_SIGNATURE/hyprland.log | grep --line-buffered "Changed to workspace" | while read -r; do + workspaces +done diff --git a/nixos/hosts/thalassa/null/home/hyprland.nix b/nixos/hosts/thalassa/null/home/hyprland.nix new file mode 100644 index 00000000..cdc6efa4 --- /dev/null +++ b/nixos/hosts/thalassa/null/home/hyprland.nix @@ -0,0 +1,137 @@ +{ pkgs, config, ... }: { + home.file.".config/hypr/hyprpaper.conf".text = '' + ipc = off + preload = ~/cloud/Pictures/Wallpapers-Laptop/wallpaper-nix-pink.png + wallpaper = eDP-1,~/cloud/Pictures/Wallpapers-Laptop/wallpaper-nix-pink.png + ''; + + wayland.windowManager.hyprland = + let + startup-script = pkgs.writeScriptBin "startup" '' + #!${pkgs.stdenv.shell} + hyprctl setcursor Catppuccin-Frappe-Pink-Cursors ${ + builtins.toString config.home.pointerCursor.size + } + ${pkgs.hyprpaper}/bin/hyprpaper & + foot --server & + eww daemon & + eww open bar & + firefox-devedition & + webcord & + element-desktop & + ''; + in + { + enable = true; + recommendedEnvironment = true; + extraConfig = '' + exec-once=dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP + exec-once=systemctl --user import-environment WAYLAND_DISPLAY XDG_CURRENT_DESKTOP + + monitor=eDP-1,1920x1080@60,0x0,1 + monitor=eDP-1,addreserved,0,0,48,0 + monitor=,preferred,auto,1 + + windowrulev2 = workspace 1 silent,class:^(Electron)$,title:^(.*)(WebCord)(.*)$ + windowrulev2 = workspace 1 silent,title:^(Element)(.*)$ + windowrulev2 = workspace 2 silent,class:^(firefox-aurora)$ + windowrulev2 = float,class:^(firefox-aurora)$,title:^(Picture-in-Picture)$ + + general { + layout = dwindle + col.active_border = 0xfff4b8e4 + } + + input { + kb_options=caps:escape + touchpad { + natural_scroll= true + } + } + + gestures { + workspace_swipe = true + } + + misc { + no_vfr = false + disable_hyprland_logo = true + disable_splash_rendering = true + } + + dwindle { + pseudotile=true + } + + bind=SUPER,RETURN,exec,footclient + bind=SUPER,f,exec,firefox-devedition + bind=SUPER,d,exec,wofi --show run,drun + + bind=,Print,exec,grim -g "$(slurp)" -t png - | wl-copy -t image/png + bind=SUPER,W,killactive, + bind=SUPERSHIFT,Q,exit, + bind=SUPER,S,togglefloating, + bind=SUPER,P,pin, + + bindm=SUPER,mouse:272,movewindow + bindm=SUPER,mouse:273,resizewindow + + bind=SUPER,left,movefocus,l + bind=SUPER,right,movefocus,r + bind=SUPER,up,movefocus,u + bind=SUPER,down,movefocus,d + + bind=SUPER,1,workspace,1 + bind=SUPER,2,workspace,2 + bind=SUPER,3,workspace,3 + bind=SUPER,4,workspace,4 + bind=SUPER,5,workspace,5 + bind=SUPER,6,workspace,6 + bind=SUPER,7,workspace,7 + bind=SUPER,8,workspace,8 + bind=SUPER,9,workspace,9 + bind=SUPER,0,workspace,10 + bind=SUPER,grave,togglespecialworkspace + + bind=ALT,1,movetoworkspace,1 + bind=ALT,2,movetoworkspace,2 + bind=ALT,3,movetoworkspace,3 + bind=ALT,4,movetoworkspace,4 + bind=ALT,5,movetoworkspace,5 + bind=ALT,6,movetoworkspace,6 + bind=ALT,7,movetoworkspace,7 + bind=ALT,8,movetoworkspace,8 + bind=ALT,9,movetoworkspace,9 + bind=ALT,0,movetoworkspace,10 + bind=ALT,grave,movetoworkspace,special + + bind=SUPERSHIFT,1,movetoworkspacesilent,1 + bind=SUPERSHIFT,2,movetoworkspacesilent,2 + bind=SUPERSHIFT,3,movetoworkspacesilent,3 + bind=SUPERSHIFT,4,movetoworkspacesilent,4 + bind=SUPERSHIFT,5,movetoworkspacesilent,5 + bind=SUPERSHIFT,6,movetoworkspacesilent,6 + bind=SUPERSHIFT,7,movetoworkspacesilent,7 + bind=SUPERSHIFT,8,movetoworkspacesilent,8 + bind=SUPERSHIFT,9,movetoworkspacesilent,9 + bind=SUPERSHIFT,0,movetoworkspacesilent,10 + bind=SUPERSHIFT,grave,movetoworkspacesilent,special + + bind=SUPER,mouse_down,workspace,e+1 + bind=SUPER,mouse_up,workspace,e-1 + + bind=SUPER,g,togglegroup + bind=SUPER,tab,changegroupactive + bind=SUPER,m,fullscreen,1 + bind=SUPERSHIFT,m,fullscreen,0 + + bind=,XF86MonBrightnessUp,exec,brightnessctl -q s +5% + bind=,XF86MonBrightnessDown,exec,brightnessctl -q s 5%- + bind=,XF86MonRaiseVolume,exec,pamixer -i 5 + bind=,XF86MonLowerVolume,exec,pamixer -d 5 + bind=,XF86AudioMute,exec,pamixer -t + + exec-once=${startup-script}/bin/startup + ''; + }; +} diff --git a/nixos/hosts/thalassa/null/home/neovim.nix b/nixos/hosts/thalassa/null/home/neovim.nix new file mode 100644 index 00000000..a6eb4fa8 --- /dev/null +++ b/nixos/hosts/thalassa/null/home/neovim.nix @@ -0,0 +1,39 @@ +{ inputs, pkgs, ... }: { + imports = [ inputs.nixvim.homeManagerModules.nixvim ]; + programs.nixvim = { + enable = true; + package = pkgs.neovim-unwrapped; + + extraPlugins = with pkgs.vimPlugins; [ catppuccin-nvim ]; + + colorscheme = "catppuccin-frappe"; + + plugins = { + nix.enable = true; + treesitter = { + enable = true; + nixGrammars = false; + ensureInstalled = [ ]; + }; + surround.enable = true; + fugitive.enable = true; + lualine = { + enable = true; + theme = "catppuccin"; + }; + telescope = { + enable = true; + extensions.fzf-native.enable = true; + }; + lsp = { + enable = true; + servers = { + rust-analyzer.enable = true; + rnix-lsp.enable = true; + pyright.enable = true; + }; + }; + nvim-cmp = { enable = true; }; + }; + }; +} diff --git a/nixos/hosts/thalassa/null/home/theme.nix b/nixos/hosts/thalassa/null/home/theme.nix new file mode 100644 index 00000000..fecec7af --- /dev/null +++ b/nixos/hosts/thalassa/null/home/theme.nix @@ -0,0 +1,127 @@ +{ lib, pkgs, config, ... }: +let + inherit (builtins) mapAttrs; + + theme = "Catppuccin-Pink-Dark"; + cursorTheme = config.home.pointerCursor.name; + colour = { + rosewater = "f2d5cf"; + flamingo = "eebebe"; + pink = "f4b8e4"; + mauve = "ca9ee6"; + red = "e78284"; + maroon = "ea999c"; + peach = "ef9f76"; + yellow = "e5c890"; + green = "a6d189"; + teal = "81c8be"; + sky = "99d1db"; + sapphire = "85c1dc"; + blue = "8caaee"; + lavender = "babbf1"; + text = "c6d0f5"; + subtext0 = "a5adce"; + subtext1 = "b5bfe2"; + overlay2 = "949cbb"; + overlay0 = "737994"; + overlay1 = "838ba7"; + surface0 = "414559"; + surface1 = "51576d"; + surface2 = "626880"; + base = "303446"; + mantle = "292c3c"; + crust = "232634"; + + hex = mapAttrs (_name: value: "#${value}") colour; + }; +in +{ + home = { + file.".xsettingsd".text = '' + Net/ThemeName "${theme}" + Gtk/CursorThemeName "${cursorTheme}" + ''; + + pointerCursor = { + name = "Catppuccin-Frappe-Pink-Cursors"; + size = 32; + package = pkgs.catppuccin-cursors.frappePink; + }; + + file.".config/eww/eww.scss".text = lib.mkBefore '' + $rosewater: ${colour.hex.rosewater}; + $flamingo: ${colour.hex.flamingo}; + $pink: ${colour.hex.pink}; + $mauve: ${colour.hex.mauve}; + $red: ${colour.hex.red}; + $maroon: ${colour.hex.maroon}; + $peach: ${colour.hex.peach}; + $yellow: ${colour.hex.yellow}; + $green: ${colour.hex.green}; + $teal: ${colour.hex.teal}; + $sky: ${colour.hex.sky}; + $sapphire: ${colour.hex.sapphire}; + $blue: ${colour.hex.blue}; + $lavender: ${colour.hex.lavender}; + $text: ${colour.hex.text}; + $subtext0: ${colour.hex.subtext0}; + $subtext1: ${colour.hex.subtext1}; + $overlay0: ${colour.hex.overlay0}; + $overlay1: ${colour.hex.overlay1}; + $overlay2: ${colour.hex.overlay2}; + $surface0: ${colour.hex.surface0}; + $surface1: ${colour.hex.surface1}; + $surface2: ${colour.hex.surface2}; + $base: ${colour.hex.base}; + $mantle: ${colour.hex.mantle}; + $crust: ${colour.hex.crust}; + ''; + }; + + gtk = { + enable = true; + theme = { + name = theme; + package = pkgs.catppuccin-gtk; + }; + iconTheme = { + name = "Arc"; + package = pkgs.arc-icon-theme; + }; + cursorTheme = { + name = cursorTheme; + inherit (config.home.pointerCursor) size package; + }; + }; + + # Note, pink and blue are switched + programs.foot.settings.colors = { + alpha = 0.8; + + foreground = colour.text; # Text + background = colour.base; # Base + regular0 = colour.surface1; # Surface 1 + regular1 = colour.red; # red + regular2 = colour.green; # green + regular3 = colour.yellow; # yellow + regular4 = colour.pink; # pink + regular5 = colour.blue; # blue + regular6 = colour.teal; # teal + regular7 = colour.subtext1; # Subtext 1 + bright0 = colour.surface2; # Surface 2 + bright1 = colour.red; # red + bright2 = colour.green; # green + bright3 = colour.yellow; # yellow + bright4 = colour.pink; # pink + bright5 = colour.blue; # blue + bright6 = colour.teal; # teal + bright7 = colour.subtext0; # Subtext 0 + }; + + programs.mako = { + backgroundColor = colour.hex.mantle; + borderColor = colour.hex.pink; + textColor = colour.hex.text; + borderRadius = 5; + }; +} diff --git a/nixos/hosts/thalassa/null/networking.nix b/nixos/hosts/thalassa/null/networking.nix new file mode 100644 index 00000000..ccf7a8a9 --- /dev/null +++ b/nixos/hosts/thalassa/null/networking.nix @@ -0,0 +1,76 @@ +_: { + services.v.dns = { + enable = true; + openFirewall = false; + mode = "laptop"; + }; + + services.mullvad-vpn.enable = true; + + networking = { + useDHCP = true; + dhcpcd.wait = "background"; + wireless = { + enable = true; + environmentFile = "/var/lib/secrets/wireless.env"; + userControlled.enable = true; + networks = { + eduroam = { + auth = '' + proto=RSN + key_mgmt=WPA-EAP + eap=PEAP + identity="vroest@tudelft.nl" + password=hash:@EDUROAM_PASSWORD_HASH@ + domain_suffix_match="radius.tudelft.nl" + anonymous_identity="anonymous@tudelft.nl" + phase1="peaplabel=0" + phase2="auth=MSCHAPV2" + ca_cert="/etc/ssl/certs/ca-bundle.crt" + ''; + }; + "Pikachu 5G" = { psk = "@PIKACHU_PASSWORD@"; }; + "sha256('yeet')" = { psk = "@SHA256_PASSWORD@"; }; + "wired" = { psk = "@WIRED_PASSWORD@"; }; + "meowy hotspot" = { psk = "@HOTSPOT_PASSWORD@"; }; + "WiFi Roest" = { psk = "@WIFI_ROEST_PASSWORD@"; }; + }; + }; + + nameservers = [ + "127.0.0.1" # Use locally deployed unbound + "::1" + ]; + + firewall.allowedUDPPorts = [ 51820 ]; + + # Maybe switch to wg-quick + wireguard.interfaces.wg0 = { + ips = [ "10.100.0.4/24" ]; + listenPort = 51820; + privateKeyFile = "/var/lib/secrets/wg_key"; + + peers = [ + { + # Delft + publicKey = "kDIO3BJSYlDwRXc2zt9tR1LqKJzIPrulaRmdiYkg+m0="; + allowedIPs = [ "10.100.0.1" "10.42.42.0/23" ]; + endpoint = "195.85.167.34:51820"; + persistentKeepalive = 25; + } + { + # Aerdenhout + publicKey = "KgqLhmUMX6kyTjRoa/GOCrZOvXNE5HWYuOr/T3v8/VI="; + allowedIPs = [ + "10.100.0.5" + "192.168.0.0/24" # to avoid being less specific than a LAN + "192.168.1.0/24" + "10.10.10.0/24" + ]; + endpoint = "80.60.83.220:51820"; + persistentKeepalive = 25; + } + ]; + }; + }; +} diff --git a/nixos/hosts/thalassa/null/rescue-boot.nix b/nixos/hosts/thalassa/null/rescue-boot.nix new file mode 100644 index 00000000..a6cf2a2c --- /dev/null +++ b/nixos/hosts/thalassa/null/rescue-boot.nix @@ -0,0 +1,35 @@ +{ pkgs, ... }: +let + # TODO: slim down size + netboot = import (pkgs.path + "/nixos/lib/eval-config.nix") { + inherit (pkgs) system; + modules = [ + (pkgs.path + "/nixos/modules/installer/netboot/netboot-minimal.nix") + module + ]; + }; + module = { + system.stateVersion = "22.11"; + boot.supportedFilesystems = [ "btrfs" "ext4" ]; + environment.systemPackages = with pkgs; [ git ]; + }; +in +{ + boot.loader.systemd-boot = { + extraEntries = { + "rescue.conf" = '' + title Rescue Boot + linux /rescue-kernel + initrd /rescue-initrd + options init=${netboot.config.system.build.toplevel}/init ${ + toString netboot.config.boot.kernelParams + } + ''; + }; + + extraFiles = { + "rescue-kernel" = "${netboot.config.system.build.kernel}/bzImage"; + "rescue-initrd" = "${netboot.config.system.build.netbootRamdisk}/initrd"; + }; + }; +} diff --git a/nixos/pkgs/default.nix b/nixos/pkgs/default.nix new file mode 100644 index 00000000..5f7180fc --- /dev/null +++ b/nixos/pkgs/default.nix @@ -0,0 +1,29 @@ +# nix-build -E 'with import {}; callPackage ./default.nix {}' +_final: prev: { + v = { + glitch-soc = prev.callPackage ./glitch-soc { }; + + unbound = prev.unbound.override { + withSystemd = true; + withDoH = true; + withDNSCrypt = true; + withTFO = true; + }; + + dnd-5e-latex-template = prev.callPackage ./dnd-5e-latex-template { }; + + roundcube-swipe = prev.callPackage ./roundcube-swipe { }; + + gitea-agatheme = prev.callPackage ./gitea-agatheme { }; + + # nix-shell -p "(vscode-with-extensions.override {vscodeExtensions = with vscode-extensions; [ jnoortheen.nix-ide ]; })" -I nixpkgs=. + vscode-extensions = { + platformio.platformio-ide = + prev.callPackage ./vscode-extensions/platformio.nix { }; + }; + + }; + + plex-plexpass = prev.callPackage ./plex-pass { }; + plexRaw-plexpass = prev.callPackage ./plex-pass/raw.nix { }; +} diff --git a/nixos/pkgs/dnd-5e-latex-template/default.nix b/nixos/pkgs/dnd-5e-latex-template/default.nix new file mode 100644 index 00000000..c295de61 --- /dev/null +++ b/nixos/pkgs/dnd-5e-latex-template/default.nix @@ -0,0 +1,30 @@ +{ lib, stdenvNoCC, fetchFromGitHub }: +stdenvNoCC.mkDerivation rec { + pname = "dnd-5e-latex-template"; + version = "0.8.0"; + tlType = "run"; + + src = fetchFromGitHub { + owner = "rpgtex"; + repo = "DND-5e-LaTeX-Template"; + rev = "d611f61d2d0f54e621641cffe87b49ca216ccf1a"; + sha256 = "sha256-jSYC0iduKGoUaYI1jrH0cakC45AMug9UodERqsvwVxw="; + }; + + phases = [ "installPhase" ]; + + installPhase = '' + runHook preInstall + + path="$out/tex/latex/${pname}" + mkdir -p "$path" + cp -r $src/* $path + + runHook postInstall + ''; + + meta = { + description = "DnD 5e latex template"; + license = lib.licenses.mit; + }; +} diff --git a/nixos/pkgs/gitea-agatheme/default.nix b/nixos/pkgs/gitea-agatheme/default.nix new file mode 100644 index 00000000..0901a05c --- /dev/null +++ b/nixos/pkgs/gitea-agatheme/default.nix @@ -0,0 +1,21 @@ +{ stdenvNoCC, fetchurl, lib }: +stdenvNoCC.mkDerivation { + pname = "gitea-agatheme"; + version = "1.2"; + + src = fetchurl { + url = + "https://git.lain.faith/attachments/290e2304-92a3-4991-8703-fbbf52f31340"; + sha256 = "424f4e232c7d759485cdf1bcde9edde50f2992cf6bde61c21f71eae03a905543"; + }; + + phases = [ "installPhase" ]; + + installPhase = '' + cp $src $out + ''; + + meta = with lib; { + description = "Gitea/Forgejo purple theme"; + }; +} diff --git a/nixos/pkgs/glitch-soc/default.nix b/nixos/pkgs/glitch-soc/default.nix new file mode 100644 index 00000000..28ac565f --- /dev/null +++ b/nixos/pkgs/glitch-soc/default.nix @@ -0,0 +1,148 @@ +{ lib +, stdenv +, nodejs-slim +, bundlerEnv +, nixosTests +, yarn +, callPackage +, imagemagick +, ffmpeg +, file +, ruby_3_0 +, writeShellScript +, fetchYarnDeps +, fixup_yarn_lock + + # Allow building a fork or custom version of Mastodon: +, pname ? "mastodon" +, version ? import ./version.nix +, srcOverride ? null +, dependenciesDir ? ./. # Should contain gemset.nix, yarn.nix and package.json. +}: + +stdenv.mkDerivation rec { + inherit pname version; + + # Using overrideAttrs on src does not build the gems and modules with the overridden src. + # Putting the callPackage up in the arguments list also does not work. + src = + if srcOverride != null then srcOverride else callPackage ./source.nix { }; + + mastodon-gems = bundlerEnv { + name = "${pname}-gems-${version}"; + inherit version; + ruby = ruby_3_0; + gemdir = src; + gemset = dependenciesDir + "/gemset.nix"; + # This fix (copied from https://github.com/NixOS/nixpkgs/pull/76765) replaces the gem + # symlinks with directories, resolving this error when running rake: + # /nix/store/451rhxkggw53h7253izpbq55nrhs7iv0-mastodon-gems-3.0.1/lib/ruby/gems/2.6.0/gems/bundler-1.17.3/lib/bundler/settings.rb:6:in `': uninitialized constant Bundler::Settings (NameError) + postBuild = '' + for gem in "$out"/lib/ruby/gems/*/gems/*; do + cp -a "$gem/" "$gem.new" + rm "$gem" + # needed on macOS, otherwise the mv yields permission denied + chmod +w "$gem.new" + mv "$gem.new" "$gem" + done + ''; + }; + + mastodon-modules = stdenv.mkDerivation { + pname = "${pname}-modules"; + inherit src version; + + yarnOfflineCache = fetchYarnDeps { + yarnLock = "${src}/yarn.lock"; + sha256 = "sha256-iSqMe4B9ZEFPAw7uXgnbTWBnXg89WM/3gnDbQAUJv2E="; + # sha256 = lib.fakeSha256; + }; + + nativeBuildInputs = [ + fixup_yarn_lock + nodejs-slim + yarn + mastodon-gems + mastodon-gems.wrappedRuby + ]; + + RAILS_ENV = "production"; + NODE_ENV = "production"; + + buildPhase = '' + export HOME=$PWD + # This option is needed for openssl-3 compatibility + # Otherwise we encounter this upstream issue: https://github.com/mastodon/mastodon/issues/17924 + export NODE_OPTIONS=--openssl-legacy-provider + fixup_yarn_lock ~/yarn.lock + yarn config --offline set yarn-offline-mirror $yarnOfflineCache + yarn install --offline --frozen-lockfile --ignore-engines --ignore-scripts --no-progress + + patchShebangs ~/bin + patchShebangs ~/node_modules + + # skip running yarn install + rm -rf ~/bin/yarn + + OTP_SECRET=precompile_placeholder SECRET_KEY_BASE=precompile_placeholder \ + rails assets:precompile + yarn cache clean --offline + rm -rf ~/node_modules/.cache + ''; + + installPhase = '' + mkdir -p $out/public + cp -r node_modules $out/node_modules + cp -r public/assets $out/public + cp -r public/packs $out/public + ''; + }; + + propagatedBuildInputs = [ imagemagick ffmpeg file mastodon-gems.wrappedRuby ]; + buildInputs = [ mastodon-gems nodejs-slim ]; + + buildPhase = '' + ln -s ${mastodon-modules}/node_modules node_modules + ln -s ${mastodon-modules}/public/assets public/assets + ln -s ${mastodon-modules}/public/packs public/packs + + patchShebangs bin/ + for b in $(ls ${mastodon-gems}/bin/) + do + if [ ! -f bin/$b ]; then + ln -s ${mastodon-gems}/bin/$b bin/$b + fi + done + + rm -rf log + ln -s /var/log/mastodon log + ln -s /tmp tmp + ''; + + installPhase = + let + run-streaming = writeShellScript "run-streaming.sh" '' + # NixOS helper script to consistently use the same NodeJS version the package was built with. + ${nodejs-slim}/bin/node ./streaming + ''; + in + '' + mkdir -p $out + cp -r * $out/ + ln -s ${run-streaming} $out/run-streaming.sh + ''; + + passthru = { + tests.mastodon = nixosTests.mastodon; + updateScript = callPackage ./update.nix { }; + }; + + meta = with lib; { + description = + "Self-hosted, globally interconnected microblogging software based on ActivityPub"; + homepage = "https://joinmastodon.org"; + license = licenses.agpl3Plus; + platforms = [ "x86_64-linux" "i686-linux" "aarch64-linux" ]; + maintainers = with maintainers; [ happy-river erictapen izorkin ]; + }; +} diff --git a/nixos/pkgs/glitch-soc/gemset.nix b/nixos/pkgs/glitch-soc/gemset.nix new file mode 100644 index 00000000..0fc8dfa4 --- /dev/null +++ b/nixos/pkgs/glitch-soc/gemset.nix @@ -0,0 +1,3343 @@ +{ + actioncable = { + dependencies = [ "actionpack" "activesupport" "nio4r" "websocket-driver" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1i98vjh8l1xrf0ihdpvgq7mz7cfj4aww77swjlwljcgfb45868d9"; + type = "gem"; + }; + version = "7.0.7.2"; + }; + actionmailbox = { + dependencies = [ "actionpack" "activejob" "activerecord" "activestorage" "activesupport" "mail" "net-imap" "net-pop" "net-smtp" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "093snb186qdvj1isss0k74ym7kkaq7zwfa5dwmrc0xn8kwhaxbik"; + type = "gem"; + }; + version = "7.0.7.2"; + }; + actionmailer = { + dependencies = [ "actionpack" "actionview" "activejob" "activesupport" "mail" "net-imap" "net-pop" "net-smtp" "rails-dom-testing" ]; + groups = [ "default" "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "180ik1gkwy8lqwg0427k0hlivmz206xa453p5c221hpqk8an340f"; + type = "gem"; + }; + version = "7.0.7.2"; + }; + actionpack = { + dependencies = [ "actionview" "activesupport" "rack" "rack-test" "rails-dom-testing" "rails-html-sanitizer" ]; + groups = [ "default" "development" "pam_authentication" "production" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0qamc5ly521wk9i1658h9jv7avmyyp92kffa1da2fn5zk0wgyhf4"; + type = "gem"; + }; + version = "7.0.7.2"; + }; + actiontext = { + dependencies = [ "actionpack" "activerecord" "activestorage" "activesupport" "globalid" "nokogiri" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0cx0zg6y0w5njl721vqx7bn0kqj5c9zbvingvl5ll20gpyzsp7nj"; + type = "gem"; + }; + version = "7.0.7.2"; + }; + actionview = { + dependencies = [ "activesupport" "builder" "erubi" "rails-dom-testing" "rails-html-sanitizer" ]; + groups = [ "default" "development" "pam_authentication" "production" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "151zxb61bb6q7g0sn34qz79k8bg02vmb8mmnsn0fr15lxw92dfhm"; + type = "gem"; + }; + version = "7.0.7.2"; + }; + active_model_serializers = { + dependencies = [ "actionpack" "activemodel" "case_transform" "jsonapi-renderer" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0xdp7cpj3yj3wl4vj0nqq44kzjavlxi1wq3cf9zp0whkir0ym0gy"; + type = "gem"; + }; + version = "0.10.13"; + }; + activejob = { + dependencies = [ "activesupport" "globalid" ]; + groups = [ "default" "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "191320166dxiq9a4lwbi1nmlq7phsfi0yr1hg2smprlwsa0vv3kd"; + type = "gem"; + }; + version = "7.0.7.2"; + }; + activemodel = { + dependencies = [ "activesupport" ]; + groups = [ "default" "development" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1crjq1dznlbsrwd5yijxraz1591xmg4vdcwwnmrw4nh6hrwq5fj5"; + type = "gem"; + }; + version = "7.0.7.2"; + }; + activerecord = { + dependencies = [ "activemodel" "activesupport" ]; + groups = [ "default" "development" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "03vrssdqaqm41w27s21r37skdfxa41midvjy37i2zh3rnbnq8ps2"; + type = "gem"; + }; + version = "7.0.7.2"; + }; + activestorage = { + dependencies = [ "actionpack" "activejob" "activerecord" "activesupport" "marcel" "mini_mime" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1w7l2i0n84axr4da7y381k8y0wa1y3rr3k3zrkhp938ldwk7j7cg"; + type = "gem"; + }; + version = "7.0.7.2"; + }; + activesupport = { + dependencies = [ "concurrent-ruby" "i18n" "minitest" "tzinfo" ]; + groups = [ "default" "development" "pam_authentication" "production" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1vlzcnyqlbchaq85phmdv73ydlc18xpvxy1cbsk191cwd29i7q32"; + type = "gem"; + }; + version = "7.0.7.2"; + }; + addressable = { + dependencies = [ "public_suffix" ]; + groups = [ "default" "development" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "05r1fwy487klqkya7vzia8hnklcxy4vr92m9dmni3prfwk6zpw33"; + type = "gem"; + }; + version = "2.8.5"; + }; + aes_key_wrap = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "19bn0y70qm6mfj4y1m0j3s8ggh6dvxwrwrj5vfamhdrpddsz8ddr"; + type = "gem"; + }; + version = "1.1.0"; + }; + airbrussh = { + dependencies = [ "sshkit" ]; + groups = [ "default" "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0x55y3ynkda76pwnsvrrjlvxfcc7yn1irad8radll9c9cif41jqv"; + type = "gem"; + }; + version = "1.4.1"; + }; + android_key_attestation = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "02spc1sh7zsljl02v9d5rdb717b628vw2k7jkkplifyjk4db0zj6"; + type = "gem"; + }; + version = "0.3.0"; + }; + annotate = { + dependencies = [ "activerecord" "rake" ]; + groups = [ "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1lw0fxb5mirsdp3bp20gjyvs7clvi19jbxnrm2ihm20kzfhvlqcs"; + type = "gem"; + }; + version = "3.2.0"; + }; + ast = { + groups = [ "default" "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "04nc8x27hlzlrr5c2gn7mar4vdr0apw5xg22wp6m8dx3wqr04a0y"; + type = "gem"; + }; + version = "2.4.2"; + }; + attr_encrypted = { + dependencies = [ "encryptor" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "034x6mbrv9apd83v99v9pm8vl3d17w5bbwws26gr4wv95fylmgnc"; + type = "gem"; + }; + version = "4.0.0"; + }; + attr_required = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1g22axmi2rhhy7w8c3x6gppsawxqavbrnxpnmphh22fk7cwi0kh2"; + type = "gem"; + }; + version = "1.0.1"; + }; + awrence = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0gj8f8c54r9cabkm41s59sa1ca5wpbipw7gq3sfl87x9296227fx"; + type = "gem"; + }; + version = "1.2.1"; + }; + aws-eventstream = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1pyis1nvnbjxk12a43xvgj2gv0mvp4cnkc1gzw0v1018r61399gz"; + type = "gem"; + }; + version = "1.2.0"; + }; + aws-partitions = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0m2kha6ip4ynhvl1l8z4vg0j96ngq4f2v6jl4j2y27m2kzmgcxz5"; + type = "gem"; + }; + version = "1.809.0"; + }; + aws-sdk-core = { + dependencies = [ "aws-eventstream" "aws-partitions" "aws-sigv4" "jmespath" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0xjw9cf6ldbw50xi5ric8d63r8kybpsvaqxh2v6n7374hfady73i"; + type = "gem"; + }; + version = "3.181.0"; + }; + aws-sdk-kms = { + dependencies = [ "aws-sdk-core" "aws-sigv4" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1zr5w2cjd895abyn7y5gifhq37bxcinssvdx2l1qmlkllbdxbwq0"; + type = "gem"; + }; + version = "1.71.0"; + }; + aws-sdk-s3 = { + dependencies = [ "aws-sdk-core" "aws-sdk-kms" "aws-sigv4" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0yymj15nwnvam95lw5fxwxx7b6xm4hkj8z7byzvjmx9aji1x245m"; + type = "gem"; + }; + version = "1.133.0"; + }; + aws-sigv4 = { + dependencies = [ "aws-eventstream" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0z889c4c1w7wsjm3szg64ay5j51kjl4pdf94nlr1yks2rlanm7na"; + type = "gem"; + }; + version = "1.6.0"; + }; + azure-storage-blob = { + dependencies = [ "azure-storage-common" "nokogiri" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0qq3knsy7nj7a0r8m19spg2bgzns9b3j5vjbs9mpg49whhc63dv1"; + type = "gem"; + }; + version = "2.0.3"; + }; + azure-storage-common = { + dependencies = [ "faraday" "faraday_middleware" "net-http-persistent" "nokogiri" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0swmsvvpmy8cdcl305p3dl2pi7m3dqjd7zywfcxmhsz0n2m4v3v0"; + type = "gem"; + }; + version = "2.0.4"; + }; + base64 = { + groups = [ "default" "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0cydk9p2cv25qysm0sn2pb97fcpz1isa7n3c8xm1gd99li8x6x8c"; + type = "gem"; + }; + version = "0.1.1"; + }; + bcrypt = { + groups = [ "default" "pam_authentication" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "048z3fvcknqx7ikkhrcrykxlqmf9bzc7l0y5h1cnvrc9n2qf0k8m"; + type = "gem"; + }; + version = "3.1.18"; + }; + better_errors = { + dependencies = [ "erubi" "rack" "rouge" ]; + groups = [ "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0wqazisnn6hn1wsza412xribpw5wzx6b5z5p4mcpfgizr6xg367p"; + type = "gem"; + }; + version = "2.10.1"; + }; + better_html = { + dependencies = [ "actionview" "activesupport" "ast" "erubi" "parser" "smart_properties" ]; + groups = [ "default" "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1y090dmgjxr3yzxi3pg5jgirkmyfdrmjhabmzmhg5i8ssiqr2gdz"; + type = "gem"; + }; + version = "2.0.1"; + }; + bindata = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "04y4zgh4bbcb8wmkxwfqg4saky1d1f3xw8z6yk543q13h8ky8rz5"; + type = "gem"; + }; + version = "2.4.15"; + }; + binding_of_caller = { + dependencies = [ "debug_inspector" ]; + groups = [ "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "078n2dkpgsivcf0pr50981w95nfc2bsrp3wpf9wnxz1qsp8jbb9s"; + type = "gem"; + }; + version = "1.0.0"; + }; + blurhash = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "057afgqy73n8vm7k3cr4pbwm1hhqnm58lp4x7bgm5wzbs39m7xf8"; + type = "gem"; + }; + version = "0.1.7"; + }; + bootsnap = { + dependencies = [ "msgpack" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1vcg52gwl64xhhal6kwk1pc01y1klzdlnv1awyk89kb91z010x7q"; + type = "gem"; + }; + version = "1.16.0"; + }; + brakeman = { + groups = [ "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1gliwnyma9f1mpr928c79i36q51yl68dwjd3jgwvsyr4piiiqr1r"; + type = "gem"; + }; + version = "6.0.1"; + }; + browser = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0g4bcpax07kqqr9cp7cjc7i0pcij4nqpn1rdsg2wdwhzf00m6x32"; + type = "gem"; + }; + version = "5.3.1"; + }; + brpoplpush-redis_script = { + dependencies = [ "concurrent-ruby" "redis" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1nd5zj5yqmhv9lrsqz8s2dqq28v4ywy95qrw7nzhhf89dl4dq49l"; + type = "gem"; + }; + version = "0.1.3"; + }; + builder = { + groups = [ "default" "development" "pam_authentication" "production" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "045wzckxpwcqzrjr353cxnyaxgf0qg22jh00dcx7z38cys5g1jlr"; + type = "gem"; + }; + version = "3.2.4"; + }; + bundler-audit = { + dependencies = [ "thor" ]; + groups = [ "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0gdx0019vj04n1512shhdx7hwphzqmdpw4vva2k551nd47y1dixx"; + type = "gem"; + }; + version = "0.9.1"; + }; + capistrano = { + dependencies = [ "airbrussh" "i18n" "rake" "sshkit" ]; + groups = [ "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "14pflh85rrs2l8k0m286j4vaab5vad2sfqq9dncqb31z05vy29mn"; + type = "gem"; + }; + version = "3.17.3"; + }; + capistrano-bundler = { + dependencies = [ "capistrano" ]; + groups = [ "default" "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "09rndb1fa9r7mhb2sc6p3k0pcarhg8mv0kfmvd1zdb0ciwwp7514"; + type = "gem"; + }; + version = "2.1.0"; + }; + capistrano-rails = { + dependencies = [ "capistrano" "capistrano-bundler" ]; + groups = [ "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "05lk7y4qyzadzzshjyhgfgx00ggqliq7n561wkx8m331wljv7kx7"; + type = "gem"; + }; + version = "1.6.3"; + }; + capistrano-rbenv = { + dependencies = [ "capistrano" "sshkit" ]; + groups = [ "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1x9m1i5zd0wx122zw3m40zprlmxk9d47bd6w61k81wr4qsvkk3rw"; + type = "gem"; + }; + version = "2.2.0"; + }; + capistrano-yarn = { + dependencies = [ "capistrano" ]; + groups = [ "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1zdg2s061vl5b8114n909mrjb2hc1qx0i4wqx9nacsrcjgyp07l9"; + type = "gem"; + }; + version = "2.0.2"; + }; + capybara = { + dependencies = [ "addressable" "matrix" "mini_mime" "nokogiri" "rack" "rack-test" "regexp_parser" "xpath" ]; + groups = [ "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "114qm5f5vhwaaw9rj1h2lcamh46zl13v1m18jiw68zl961gwmw6n"; + type = "gem"; + }; + version = "3.39.2"; + }; + case_transform = { + dependencies = [ "activesupport" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0fzyws6spn5arqf6q604dh9mrj84a36k5hsc8z7jgcpfvhc49bg2"; + type = "gem"; + }; + version = "0.2"; + }; + cbor = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0511idr8xps9625nh3kxr68sdy6l3xy2kcz7r57g47fxb1v18jj3"; + type = "gem"; + }; + version = "0.5.9.6"; + }; + charlock_holmes = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0hybw8jw9ryvz5zrki3gc9r88jqy373m6v46ynxsdzv1ysiyr40p"; + type = "gem"; + }; + version = "0.7.7"; + }; + chewy = { + dependencies = [ "activesupport" "elasticsearch" "elasticsearch-dsl" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0zca6v8i66jkxfdfjnn9xwg21pk95qn4ic8vzfvrx49d6sb8319y"; + type = "gem"; + }; + version = "7.3.4"; + }; + chunky_png = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1znw5x86hmm9vfhidwdsijz8m38pqgmv98l9ryilvky0aldv7mc9"; + type = "gem"; + }; + version = "1.4.0"; + }; + climate_control = { + groups = [ "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0q11v0iabvr6rif0d025xh078ili5frrihlj0m04zfg7lgvagxji"; + type = "gem"; + }; + version = "0.2.0"; + }; + cocoon = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "038z97pkhvsqbh6cmyyzj58ya968p24k7r0f0rx7sa2kjvk193yh"; + type = "gem"; + }; + version = "1.2.15"; + }; + color_diff = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "01dpvqlzybpb3pkcwd9ik5sbjw283618ywvdphxslhiy8ps3kp4r"; + type = "gem"; + }; + version = "0.1"; + }; + concurrent-ruby = { + groups = [ "default" "development" "pam_authentication" "production" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0krcwb6mn0iklajwngwsg850nk8k9b35dhmc2qkbdqvmifdi2y9q"; + type = "gem"; + }; + version = "1.2.2"; + }; + connection_pool = { + groups = [ "default" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1x32mcpm2cl5492kd6lbjbaf17qsssmpx9kdyr7z1wcif2cwyh0g"; + type = "gem"; + }; + version = "2.4.1"; + }; + cose = { + dependencies = [ "cbor" "openssl-signature_algorithm" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "00c6x4ha7qiaaf88qdbyf240mk146zz78rbm4qwyaxmwlmk7q933"; + type = "gem"; + }; + version = "1.3.0"; + }; + crack = { + dependencies = [ "rexml" ]; + groups = [ "default" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1cr1kfpw3vkhysvkk3wg7c54m75kd68mbm9rs5azdjdq57xid13r"; + type = "gem"; + }; + version = "0.4.5"; + }; + crass = { + groups = [ "default" "development" "pam_authentication" "production" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0pfl5c0pyqaparxaqxi6s4gfl21bdldwiawrc0aknyvflli60lfw"; + type = "gem"; + }; + version = "1.0.6"; + }; + css_parser = { + dependencies = [ "addressable" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "04q1vin8slr3k8mp76qz0wqgap6f9kdsbryvgfq9fljhrm463kpj"; + type = "gem"; + }; + version = "1.14.0"; + }; + database_cleaner-active_record = { + dependencies = [ "activerecord" "database_cleaner-core" ]; + groups = [ "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "12hdsqnws9gyc9sxiyc8pjiwr0xa7136m1qbhmd1pk3vsrrvk13k"; + type = "gem"; + }; + version = "2.1.0"; + }; + database_cleaner-core = { + groups = [ "default" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0v44bn386ipjjh4m2kl53dal8g4d41xajn2jggnmjbhn6965fil6"; + type = "gem"; + }; + version = "2.0.1"; + }; + date = { + groups = [ "default" "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "03skfikihpx37rc27vr3hwrb057gxnmdzxhmzd4bf4jpkl0r55w1"; + type = "gem"; + }; + version = "3.3.3"; + }; + debug_inspector = { + groups = [ "default" "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "01l678ng12rby6660pmwagmyg8nccvjfgs3487xna7ay378a59ga"; + type = "gem"; + }; + version = "1.1.0"; + }; + devise = { + dependencies = [ "bcrypt" "orm_adapter" "railties" "responders" "warden" ]; + groups = [ "default" "pam_authentication" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0vpd7d61d4pfmyb2plnnv82wmczzlhw4k4gjhd2fv4r6vq8ilqqi"; + type = "gem"; + }; + version = "4.9.2"; + }; + devise-two-factor = { + dependencies = [ "activesupport" "attr_encrypted" "devise" "railties" "rotp" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1nk43p339zyp4y5vab3w3s0zbjd4xfs8qn0ymxdnz6d961dbbdm8"; + type = "gem"; + }; + version = "4.1.0"; + }; + devise_pam_authenticatable2 = { + dependencies = [ "devise" "rpam2" ]; + groups = [ "pam_authentication" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "13ipl52pkhc6vxp8ca31viwv01237bi2bfk3b1fixq1x46nf87p2"; + type = "gem"; + }; + version = "9.2.0"; + }; + diff-lcs = { + groups = [ "default" "development" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0rwvjahnp7cpmracd8x732rjgnilqv2sx7d1gfrysslc3h039fa9"; + type = "gem"; + }; + version = "1.5.0"; + }; + discard = { + dependencies = [ "activerecord" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1xavjhccyyzn9z6fz3034vgvzprc983mbrq6n9sc0drfw7m3vrip"; + type = "gem"; + }; + version = "1.2.1"; + }; + docile = { + groups = [ "default" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1lxqxgq71rqwj1lpl9q1mbhhhhhhdkkj7my341f2889pwayk85sz"; + type = "gem"; + }; + version = "1.4.0"; + }; + domain_name = { + dependencies = [ "unf" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0lcqjsmixjp52bnlgzh4lg9ppsk52x9hpwdjd53k8jnbah2602h0"; + type = "gem"; + }; + version = "0.5.20190701"; + }; + doorkeeper = { + dependencies = [ "railties" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1q2pywgyn6cbnm0fh3dln5z1qgd1g8hvb4x8rppjc1bpfxnfhi13"; + type = "gem"; + }; + version = "5.6.6"; + }; + dotenv = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1n0pi8x8ql5h1mijvm8lgn6bhq4xjb5a500p5r1krq4s6j9lg565"; + type = "gem"; + }; + version = "2.8.1"; + }; + dotenv-rails = { + dependencies = [ "dotenv" "railties" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0v0gcbxzypcvy6fqq4gp80jb310xvdwj5n8qw9ci67g5yjvq2nxh"; + type = "gem"; + }; + version = "2.8.1"; + }; + ed25519 = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0zb2dr2ihb1qiknn5iaj1ha1w9p7lj9yq5waasndlfadz225ajji"; + type = "gem"; + }; + version = "1.3.0"; + }; + elasticsearch = { + dependencies = [ "elasticsearch-api" "elasticsearch-transport" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0havyxmvl157a653prspnbhgdchlx44xqxl170v1im5ggxwavcaq"; + type = "gem"; + }; + version = "7.13.3"; + }; + elasticsearch-api = { + dependencies = [ "multi_json" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0bmssarkk7lqkjdn8c9j7jvxcnn4hg1zcmhsky8bfvc99k33b3w8"; + type = "gem"; + }; + version = "7.13.3"; + }; + elasticsearch-dsl = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "174m3fwm3mawbkjg2xbmqvljq7ava4s95m8vpg5khcvfj506wxfk"; + type = "gem"; + }; + version = "0.1.10"; + }; + elasticsearch-transport = { + dependencies = [ "faraday" "multi_json" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0blfii8qvj0m6bg9sbfynxc40in7zfmw2wpi4clv7d9gclk053db"; + type = "gem"; + }; + version = "7.13.3"; + }; + encryptor = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0s8rvfl0vn8w7k1sgkc234060jh468s3zd45xa64p1jdmfa3zwmb"; + type = "gem"; + }; + version = "3.0.0"; + }; + erubi = { + groups = [ "default" "development" "pam_authentication" "production" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "08s75vs9cxlc4r1q2bjg4br8g9wc5lc5x5vl0vv4zq5ivxsdpgi7"; + type = "gem"; + }; + version = "1.12.0"; + }; + et-orbi = { + dependencies = [ "tzinfo" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1d2z4ky2v15dpcz672i2p7lb2nc793dasq3yq3660h2az53kss9v"; + type = "gem"; + }; + version = "1.2.7"; + }; + excon = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "08r6qgbpkxxsihjmlspk3l1sr69q5hx35p1l4wp7rmkbzys89867"; + type = "gem"; + }; + version = "0.100.0"; + }; + fabrication = { + groups = [ "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0bxssmjp49whzq2zv7w751gr4nkdaiwcxd1vda0byigwyrnj6f5q"; + type = "gem"; + }; + version = "2.30.0"; + }; + faker = { + dependencies = [ "i18n" ]; + groups = [ "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0ysiqlvyy1351bzx7h92r93a35s32l8giyf9bac6sgr142sh3cnn"; + type = "gem"; + }; + version = "3.2.1"; + }; + faraday = { + dependencies = [ "faraday-em_http" "faraday-em_synchrony" "faraday-excon" "faraday-httpclient" "faraday-multipart" "faraday-net_http" "faraday-net_http_persistent" "faraday-patron" "faraday-rack" "faraday-retry" "ruby2_keywords" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1c760q0ks4vj4wmaa7nh1dgvgqiwaw0mjr7v8cymy7i3ffgjxx90"; + type = "gem"; + }; + version = "1.10.3"; + }; + faraday-em_http = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "12cnqpbak4vhikrh2cdn94assh3yxza8rq2p9w2j34bqg5q4qgbs"; + type = "gem"; + }; + version = "1.0.0"; + }; + faraday-em_synchrony = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1vgrbhkp83sngv6k4mii9f2s9v5lmp693hylfxp2ssfc60fas3a6"; + type = "gem"; + }; + version = "1.0.0"; + }; + faraday-excon = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0h09wkb0k0bhm6dqsd47ac601qiaah8qdzjh8gvxfd376x1chmdh"; + type = "gem"; + }; + version = "1.1.0"; + }; + faraday-httpclient = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0fyk0jd3ks7fdn8nv3spnwjpzx2lmxmg2gh4inz3by1zjzqg33sc"; + type = "gem"; + }; + version = "1.0.1"; + }; + faraday-multipart = { + dependencies = [ "multipart-post" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "09871c4hd7s5ws1wl4gs7js1k2wlby6v947m2bbzg43pnld044lh"; + type = "gem"; + }; + version = "1.0.4"; + }; + faraday-net_http = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1fi8sda5hc54v1w3mqfl5yz09nhx35kglyx72w7b8xxvdr0cwi9j"; + type = "gem"; + }; + version = "1.0.1"; + }; + faraday-net_http_persistent = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0dc36ih95qw3rlccffcb0vgxjhmipsvxhn6cw71l7ffs0f7vq30b"; + type = "gem"; + }; + version = "1.2.0"; + }; + faraday-patron = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "19wgsgfq0xkski1g7m96snv39la3zxz6x7nbdgiwhg5v82rxfb6w"; + type = "gem"; + }; + version = "1.0.0"; + }; + faraday-rack = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1h184g4vqql5jv9s9im6igy00jp6mrah2h14py6mpf9bkabfqq7g"; + type = "gem"; + }; + version = "1.0.0"; + }; + faraday-retry = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "153i967yrwnswqgvnnajgwp981k9p50ys1h80yz3q94rygs59ldd"; + type = "gem"; + }; + version = "1.0.3"; + }; + faraday_middleware = { + dependencies = [ "faraday" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1bw8mfh4yin2xk7138rg3fhb2p5g2dlmdma88k82psah9mbmvlfy"; + type = "gem"; + }; + version = "1.2.0"; + }; + fast_blank = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1shpmamyzyhyxmv95r96ja5rylzaw60r19647d0fdm7y2h2c77r6"; + type = "gem"; + }; + version = "1.0.1"; + }; + fastimage = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1pd7pamzhdz2w0fbcvsfn2nyslznvphnwj16zw35g2b28zd2xyzx"; + type = "gem"; + }; + version = "2.2.7"; + }; + ffi = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1862ydmclzy1a0cjbvm8dz7847d9rch495ib0zb64y84d3xd4bkg"; + type = "gem"; + }; + version = "1.15.5"; + }; + ffi-compiler = { + dependencies = [ "ffi" "rake" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0c2caqm9wqnbidcb8dj4wd3s902z15qmgxplwyfyqbwa0ydki7q1"; + type = "gem"; + }; + version = "1.0.1"; + }; + fog-core = { + dependencies = [ "builder" "excon" "formatador" "mime-types" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1agd6xgzk0rxrsjdpn94v4hy89s0nm2cs4zg2p880w2dan9xgrak"; + type = "gem"; + }; + version = "2.1.0"; + }; + fog-json = { + dependencies = [ "fog-core" "multi_json" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1zj8llzc119zafbmfa4ai3z5s7c4vp9akfs0f9l2piyvcarmlkyx"; + type = "gem"; + }; + version = "1.2.0"; + }; + fog-openstack = { + dependencies = [ "fog-core" "fog-json" "ipaddress" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "11j18h61d3p0pcp9k5346lbj1lahab1dqybkrx9338932lmjn7ap"; + type = "gem"; + }; + version = "0.3.10"; + }; + formatador = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0mprf1dwznz5ld0q1jpbyl59fwnwk6azspnd0am7zz7kfg3pxhv5"; + type = "gem"; + }; + version = "0.3.0"; + }; + fugit = { + dependencies = [ "et-orbi" "raabro" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1cm2lrvhrpqq19hbdsxf4lq2nkb2qdldbdxh3gvi15l62dlb5zqq"; + type = "gem"; + }; + version = "1.8.1"; + }; + fuubar = { + dependencies = [ "rspec-core" "ruby-progressbar" ]; + groups = [ "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1028vn7j3kc5qqwswrf3has3qm4j9xva70xmzb3n29i89f0afwmj"; + type = "gem"; + }; + version = "2.5.1"; + }; + globalid = { + dependencies = [ "activesupport" ]; + groups = [ "default" "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0kqm5ndzaybpnpxqiqkc41k4ksyxl41ln8qqr6kb130cdxsf2dxk"; + type = "gem"; + }; + version = "1.1.0"; + }; + haml = { + dependencies = [ "temple" "thor" "tilt" ]; + groups = [ "default" "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "154svzqlkdq7gslv3p8mfih28gbw4gsj4pd8wr1wpwz6nyzmhh8m"; + type = "gem"; + }; + version = "6.1.2"; + }; + haml-rails = { + dependencies = [ "actionpack" "activesupport" "haml" "railties" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1sjrdwc4azzfpsp2xk0365z031482gcrs0c54d5wx0igkqca0fr7"; + type = "gem"; + }; + version = "2.1.0"; + }; + haml_lint = { + dependencies = [ "haml" "parallel" "rainbow" "rubocop" "sysexits" ]; + groups = [ "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1qics7sll6yw7fm499q4b1frfr5f3gav94ach0fwy49zprl9yk33"; + type = "gem"; + }; + version = "0.50.0"; + }; + hashdiff = { + groups = [ "default" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1nynpl0xbj0nphqx1qlmyggq58ms1phf5i03hk64wcc0a17x1m1c"; + type = "gem"; + }; + version = "1.0.1"; + }; + hashie = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1nh3arcrbz1rc1cr59qm53sdhqm137b258y8rcb4cvd3y98lwv4x"; + type = "gem"; + }; + version = "5.0.0"; + }; + hcaptcha = { + dependencies = [ "json" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0fh6391zlv2ikvzqj2gymb70k1avk1j9da8bzgw0scsz2wqq98m2"; + type = "gem"; + }; + version = "7.1.0"; + }; + highline = { + groups = [ "default" "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1f8cr014j7mdqpdb9q17fp5vb5b8n1pswqaif91s3ylg5x3pygfn"; + type = "gem"; + }; + version = "2.1.0"; + }; + hiredis = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "04jj8k7lxqxw24sp0jiravigdkgsyrpprxpxm71ba93x1wr2w1bz"; + type = "gem"; + }; + version = "0.6.3"; + }; + hkdf = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "04fixg0a51n4vy0j6c1hvisa2yl33m3jrrpxpb5sq6j511vjriil"; + type = "gem"; + }; + version = "0.3.0"; + }; + htmlentities = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1nkklqsn8ir8wizzlakncfv42i32wc0w9hxp00hvdlgjr7376nhj"; + type = "gem"; + }; + version = "4.3.4"; + }; + http = { + dependencies = [ "addressable" "http-cookie" "http-form_data" "llhttp-ffi" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1bzb8p31kzv6q5p4z5xq88mnqk414rrw0y5rkhpnvpl29x5c3bpw"; + type = "gem"; + }; + version = "5.1.1"; + }; + http-cookie = { + dependencies = [ "domain_name" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "13rilvlv8kwbzqfb644qp6hrbsj82cbqmnzcvqip1p6vqx36sxbk"; + type = "gem"; + }; + version = "1.0.5"; + }; + http-form_data = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1wx591jdhy84901pklh1n9sgh74gnvq1qyqxwchni1yrc49ynknc"; + type = "gem"; + }; + version = "2.3.0"; + }; + http_accept_language = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0d0nlfz9vm4jr1l6q0chx4rp2hrnrfbx3gadc1dz930lbbaz0hq0"; + type = "gem"; + }; + version = "2.1.1"; + }; + httpclient = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "19mxmvghp7ki3klsxwrlwr431li7hm1lczhhj8z4qihl2acy8l99"; + type = "gem"; + }; + version = "2.8.3"; + }; + httplog = { + dependencies = [ "rack" "rainbow" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0zjsgrlvwpqsnrza4ijlxjld4550c661sgbqp2j2wp638nlnls1a"; + type = "gem"; + }; + version = "1.6.2"; + }; + i18n = { + dependencies = [ "concurrent-ruby" ]; + groups = [ "default" "development" "pam_authentication" "production" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0qaamqsh5f3szhcakkak8ikxlzxqnv49n2p7504hcz2l0f4nj0wx"; + type = "gem"; + }; + version = "1.14.1"; + }; + i18n-tasks = { + dependencies = [ "activesupport" "ast" "better_html" "erubi" "highline" "i18n" "parser" "rails-i18n" "rainbow" "terminal-table" ]; + groups = [ "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "19zkcsqwzc3i6vizj26mxxww6m5grv9zmp6yxyswbqq9kyzb081z"; + type = "gem"; + }; + version = "1.0.12"; + }; + idn-ruby = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0dy04jx3n1ddz744b80mg7hp87miysnjp0h21lqr43hpmhdglxih"; + type = "gem"; + }; + version = "0.1.5"; + }; + ipaddress = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1x86s0s11w202j6ka40jbmywkrx8fhq8xiy8mwvnkhllj57hqr45"; + type = "gem"; + }; + version = "0.8.3"; + }; + jmespath = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1cdw9vw2qly7q7r41s7phnac264rbsdqgj4l0h4nqgbjb157g393"; + type = "gem"; + }; + version = "1.6.2"; + }; + json = { + groups = [ "default" "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0nalhin1gda4v8ybk6lq8f407cgfrj6qzn234yra4ipkmlbfmal6"; + type = "gem"; + }; + version = "2.6.3"; + }; + json-canonicalization = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1rvsalsrs8njk2gqxgq0ydg5cd02jqdawskbq2ccz663qxz8wwq5"; + type = "gem"; + }; + version = "0.3.2"; + }; + json-jwt = { + dependencies = [ "activesupport" "aes_key_wrap" "bindata" "httpclient" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "04315mf4p9qa97grdfqv922paghzdfrbb982ap0p99rqwla4znv6"; + type = "gem"; + }; + version = "1.15.3"; + }; + json-ld = { + dependencies = [ "htmlentities" "json-canonicalization" "link_header" "multi_json" "rack" "rdf" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1z3kqacjmqs02vwwqm9di7sw7f7nchxx99v84myrrzmh64c6zfcq"; + type = "gem"; + }; + version = "3.2.5"; + }; + json-ld-preloaded = { + dependencies = [ "json-ld" "rdf" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "004s52m37b2kbw8dv4rdfm2d90h1023z1mw9zfcs0x87v8aq7zyn"; + type = "gem"; + }; + version = "3.2.2"; + }; + json-schema = { + dependencies = [ "addressable" ]; + groups = [ "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "155rygs093i8i04i38a97hs5icmqk2jkkhx76w31yxyr3bxfbgx3"; + type = "gem"; + }; + version = "4.0.0"; + }; + jsonapi-renderer = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0ys4drd0k9rw5ixf8n8fx8v0pjh792w4myh0cpdspd317l1lpi5m"; + type = "gem"; + }; + version = "0.2.2"; + }; + jwt = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "16z11alz13vfc4zs5l3fk6n51n2jw9lskvc4h4prnww0y797qd87"; + type = "gem"; + }; + version = "2.7.1"; + }; + kaminari = { + dependencies = [ "activesupport" "kaminari-actionview" "kaminari-activerecord" "kaminari-core" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0gia8irryvfhcr6bsr64kpisbgdbqjsqfgrk12a11incmpwny1y4"; + type = "gem"; + }; + version = "1.2.2"; + }; + kaminari-actionview = { + dependencies = [ "actionview" "kaminari-core" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "02f9ghl3a9b5q7l079d3yzmqjwkr4jigi7sldbps992rigygcc0k"; + type = "gem"; + }; + version = "1.2.2"; + }; + kaminari-activerecord = { + dependencies = [ "activerecord" "kaminari-core" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0c148z97s1cqivzbwrak149z7kl1rdmj7dxk6rpkasimmdxsdlqd"; + type = "gem"; + }; + version = "1.2.2"; + }; + kaminari-core = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1zw3pg6kj39y7jxakbx7if59pl28lhk98fx71ks5lr3hfgn6zliv"; + type = "gem"; + }; + version = "1.2.2"; + }; + kt-paperclip = { + dependencies = [ "activemodel" "activesupport" "marcel" "mime-types" "terrapin" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0qrv9xyxxhxr482p25f3m7nfghw66i8jl02hy9b6pwam8m1knngp"; + type = "gem"; + }; + version = "7.2.0"; + }; + language_server-protocol = { + groups = [ "default" "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0gvb1j8xsqxms9mww01rmdl78zkd72zgxaap56bhv8j45z05hp1x"; + type = "gem"; + }; + version = "3.17.0.3"; + }; + launchy = { + dependencies = [ "addressable" ]; + groups = [ "default" "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "06r43899384das2bkbrpsdxsafyyqa94il7111053idfalb4984a"; + type = "gem"; + }; + version = "2.5.2"; + }; + letter_opener = { + dependencies = [ "launchy" ]; + groups = [ "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1y5d4ip4l12v58bgazadl45iv3a5j7jp2gwg96b6jy378zn42a1d"; + type = "gem"; + }; + version = "1.8.1"; + }; + letter_opener_web = { + dependencies = [ "actionmailer" "letter_opener" "railties" "rexml" ]; + groups = [ "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0vvvaz2ngaxv0s6sj25gdvp73vd8pfl8q3jharadg18p3va0m1ik"; + type = "gem"; + }; + version = "2.0.0"; + }; + link_header = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1yamrdq4rywmnpdhbygnkkl9fdy249fg5r851nrkkxr97gj5rihm"; + type = "gem"; + }; + version = "0.0.8"; + }; + llhttp-ffi = { + dependencies = [ "ffi-compiler" "rake" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "00dh6zmqdj59rhcya0l4b9aaxq6n8xizfbil93k0g06gndyk5xz5"; + type = "gem"; + }; + version = "0.4.0"; + }; + lograge = { + dependencies = [ "actionpack" "activesupport" "railties" "request_store" ]; + groups = [ "production" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "01kdw5dbzimb89rq4zf44zf8990czb5qxvib0hzja1l4hrha8cki"; + type = "gem"; + }; + version = "0.13.0"; + }; + loofah = { + dependencies = [ "crass" "nokogiri" ]; + groups = [ "default" "development" "pam_authentication" "production" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1p744kjpb5zk2ihklbykzii77alycjc04vpnm2ch2f3cp65imlj3"; + type = "gem"; + }; + version = "2.21.3"; + }; + mail = { + dependencies = [ "mini_mime" "net-imap" "net-pop" "net-smtp" ]; + groups = [ "default" "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1bf9pysw1jfgynv692hhaycfxa8ckay1gjw5hz3madrbrynryfzc"; + type = "gem"; + }; + version = "2.8.1"; + }; + marcel = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0kky3yiwagsk8gfbzn3mvl2fxlh3b39v6nawzm4wpjs6xxvvc4x0"; + type = "gem"; + }; + version = "1.0.2"; + }; + mario-redis-lock = { + dependencies = [ "redis" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1v9wdjcjqzpns2migxp4a5b4w82mipi0fwihbqz3q2qj2qm7wc17"; + type = "gem"; + }; + version = "1.2.1"; + }; + matrix = { + groups = [ "default" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1h2cgkpzkh3dd0flnnwfq6f3nl2b1zff9lvqz8xs853ssv5kq23i"; + type = "gem"; + }; + version = "0.4.2"; + }; + md-paperclip-azure = { + dependencies = [ "addressable" "azure-storage-blob" "hashie" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1hb1a06x3i8zrhl715jf46ha8r4iy0srcpdhnmp9l14qnnhzn0l5"; + type = "gem"; + }; + version = "2.2.0"; + }; + memory_profiler = { + groups = [ "development" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1c81d68r4wx0ckbmqxlfqc2qpd94jwcmqdm0xgr0s46r48pv9k9q"; + type = "gem"; + }; + version = "1.0.1"; + }; + method_source = { + groups = [ "default" "development" "pam_authentication" "production" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1pnyh44qycnf9mzi1j6fywd5fkskv3x7nmsqrrws0rjn5dd4ayfp"; + type = "gem"; + }; + version = "1.0.0"; + }; + mime-types = { + dependencies = [ "mime-types-data" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0q8d881k1b3rbsfcdi3fx0b5vpdr5wcrhn88r2d9j7zjdkxp5mw5"; + type = "gem"; + }; + version = "3.5.1"; + }; + mime-types-data = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "17zdim7kzrh5j8c97vjqp4xp78wbyz7smdp4hi5iyzk0s9imdn5a"; + type = "gem"; + }; + version = "3.2023.0808"; + }; + mini_mime = { + groups = [ "default" "development" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1vycif7pjzkr29mfk4dlqv3disc5dn0va04lkwajlpr1wkibg0c6"; + type = "gem"; + }; + version = "1.1.5"; + }; + mini_portile2 = { + groups = [ "default" "development" "pam_authentication" "production" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "02mj8mpd6ck5gpcnsimx5brzggw5h5mmmpq2djdypfq16wcw82qq"; + type = "gem"; + }; + version = "2.8.4"; + }; + minitest = { + groups = [ "default" "development" "pam_authentication" "production" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0jnpsbb2dbcs95p4is4431l2pw1l5pn7dfg3vkgb4ga464j0c5l6"; + type = "gem"; + }; + version = "5.19.0"; + }; + msgpack = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "06n7556vxr3awh92xy1k5bli98bvq4pjm08mnl68ay4fzln7lcsg"; + type = "gem"; + }; + version = "1.7.1"; + }; + multi_json = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0pb1g1y3dsiahavspyzkdy39j4q377009f6ix0bh1ag4nqw43l0z"; + type = "gem"; + }; + version = "1.15.0"; + }; + multipart-post = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0lgyysrpl50wgcb9ahg29i4p01z0irb3p9lirygma0kkfr5dgk9x"; + type = "gem"; + }; + version = "2.3.0"; + }; + net-http = { + dependencies = [ "uri" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0y55ib1v2b8prqfi9ij7hca60b1j94s2bzr6vskwi3i5735472wq"; + type = "gem"; + }; + version = "0.3.2"; + }; + net-http-persistent = { + dependencies = [ "connection_pool" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0i1as2lgnw7b4jid0gw5glv5hnxz36nmfsbr9rmxbcap72ijgy03"; + type = "gem"; + }; + version = "4.0.2"; + }; + net-imap = { + dependencies = [ "date" "net-protocol" ]; + groups = [ "default" "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0lf7wqg7czhaj51qsnmn28j7jmcxhkh3m28rl1cjrqsgjxhwj7r3"; + type = "gem"; + }; + version = "0.3.7"; + }; + net-ldap = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0xqcffn3c1564c4fizp10dzw2v5g2pabdzrcn25hq05bqhsckbar"; + type = "gem"; + }; + version = "0.18.0"; + }; + net-pop = { + dependencies = [ "net-protocol" ]; + groups = [ "default" "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1wyz41jd4zpjn0v1xsf9j778qx1vfrl24yc20cpmph8k42c4x2w4"; + type = "gem"; + }; + version = "0.1.2"; + }; + net-protocol = { + dependencies = [ "timeout" ]; + groups = [ "default" "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0dxckrlw4q1lcn3qg4mimmjazmg9bma5gllv72f8js3p36fb3b91"; + type = "gem"; + }; + version = "0.2.1"; + }; + net-scp = { + dependencies = [ "net-ssh" ]; + groups = [ "default" "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1si2nq9l6jy5n2zw1q59a5gaji7v9vhy8qx08h4fg368906ysbdk"; + type = "gem"; + }; + version = "4.0.0"; + }; + net-smtp = { + dependencies = [ "net-protocol" ]; + groups = [ "default" "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1c6md06hm5bf6rv53sk54dl2vg038pg8kglwv3rayx0vk2mdql9x"; + type = "gem"; + }; + version = "0.3.3"; + }; + net-ssh = { + groups = [ "default" "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0yx0pb5fmziz92bw8qzbh8vf20lr56nd3s6q8h0gsgr307lki687"; + type = "gem"; + }; + version = "7.1.0"; + }; + nio4r = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0w9978zwjf1qhy3amkivab0f9syz6a7k0xgydjidaf7xc831d78f"; + type = "gem"; + }; + version = "2.5.9"; + }; + nokogiri = { + dependencies = [ "mini_portile2" "racc" ]; + groups = [ "default" "development" "pam_authentication" "production" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0k9w2z0953mnjrsji74cshqqp08q7m1r6zhadw1w0g34xzjh3a74"; + type = "gem"; + }; + version = "1.15.4"; + }; + nsa = { + dependencies = [ "activesupport" "concurrent-ruby" "sidekiq" "statsd-ruby" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + fetchSubmodules = false; + rev = "e020fcc3a54d993ab45b7194d89ab720296c111b"; + sha256 = "18pbm9qkancy38v0gpb6f5k0xd8r347jl4xvj4jn98ihfhzgwygj"; + type = "git"; + url = "https://github.com/jhawthorn/nsa.git"; + }; + version = "0.2.8"; + }; + oj = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0m4vsd6i093kmyz9gckvzpnws997laldaiaf86hg5lza1ir82x7n"; + type = "gem"; + }; + version = "3.16.1"; + }; + omniauth = { + dependencies = [ "hashie" "rack" "rack-protection" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "15xjsxis357np7dy1lak39x1n8g8wxljb08wplw5i4gxi743zr7j"; + type = "gem"; + }; + version = "2.1.1"; + }; + omniauth-cas = { + dependencies = [ "addressable" "nokogiri" "omniauth" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + fetchSubmodules = false; + rev = "4211e6d05941b4a981f9a36b49ec166cecd0e271"; + sha256 = "1zs0xp062f6wk7xxy8w81838qr855kp7idbgpbrhpl319xzc1xkc"; + type = "git"; + url = "https://github.com/stanhu/omniauth-cas.git"; + }; + version = "2.0.0"; + }; + omniauth-rails_csrf_protection = { + dependencies = [ "actionpack" "omniauth" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1kwswnkyl8ym6i4wv65qh3qchqbf2n0c6lbhfgbvkds3gpmnlm7w"; + type = "gem"; + }; + version = "1.0.1"; + }; + omniauth-saml = { + dependencies = [ "omniauth" "ruby-saml" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "01k9rkg97npcgm8r4x3ja8y20hsg4zy0dcjpzafx148q4yxbg74n"; + type = "gem"; + }; + version = "2.1.0"; + }; + omniauth_openid_connect = { + dependencies = [ "omniauth" "openid_connect" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "08yl0x203k6nrshc70zawfqh79ap1c3fyka9zwwy61cvn7sih4sz"; + type = "gem"; + }; + version = "0.6.1"; + }; + openid_connect = { + dependencies = [ "activemodel" "attr_required" "json-jwt" "net-smtp" "rack-oauth2" "swd" "tzinfo" "validate_email" "validate_url" "webfinger" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1k9kdivp45v6vhzdrnl5fzhd378gjj2hl4w9bazbqnfm15rsnzc8"; + type = "gem"; + }; + version = "1.4.2"; + }; + openssl = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0c649921vg2l939z5cc3jwd8p1v49099pdhxfk7sb9qqx5wi5873"; + type = "gem"; + }; + version = "3.1.0"; + }; + openssl-signature_algorithm = { + dependencies = [ "openssl" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "103yjl68wqhl5kxaciir5jdnyi7iv9yckishdr52s5knh9g0pd53"; + type = "gem"; + }; + version = "1.3.0"; + }; + orm_adapter = { + groups = [ "default" "pam_authentication" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1fg9jpjlzf5y49qs9mlpdrgs5rpcyihq1s4k79nv9js0spjhnpda"; + type = "gem"; + }; + version = "0.5.0"; + }; + ox = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1yq0h1niimm8z6z8p1yxb104kxqw69bvbrax84598zfjxifcxhxz"; + type = "gem"; + }; + version = "2.14.17"; + }; + parallel = { + groups = [ "default" "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0jcc512l38c0c163ni3jgskvq1vc3mr8ly5pvjijzwvfml9lf597"; + type = "gem"; + }; + version = "1.23.0"; + }; + parser = { + dependencies = [ "ast" "racc" ]; + groups = [ "default" "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1swigds85jddb5gshll1g8lkmbcgbcp9bi1d4nigwvxki8smys0h"; + type = "gem"; + }; + version = "3.2.2.3"; + }; + parslet = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "01pnw6ymz6nynklqvqxs4bcai25kcvnd5x4id9z3vd1rbmlk0lfl"; + type = "gem"; + }; + version = "2.0.0"; + }; + pastel = { + dependencies = [ "tty-color" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0xash2gj08dfjvq4hy6l1z22s5v30fhizwgs10d6nviggpxsj7a8"; + type = "gem"; + }; + version = "0.8.0"; + }; + pg = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0pfj771p5a29yyyw58qacks464sl86d5m3jxjl5rlqqw2m3v5xq4"; + type = "gem"; + }; + version = "1.5.4"; + }; + pghero = { + dependencies = [ "activerecord" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "002v32dzyyr29xd9cdsqp55g5gx19skvq9b4a4hr9lrs4i1xsavm"; + type = "gem"; + }; + version = "3.3.3"; + }; + posix-spawn = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0cmb0svalqcxfzlzc5fvrci12b79x7bakasr8gkl3q5rz6di1q52"; + type = "gem"; + }; + version = "0.3.15"; + }; + premailer = { + dependencies = [ "addressable" "css_parser" "htmlentities" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "10rzwdz43yy20lwzsr2as6aivhvwjvqh4nd48sa0ga57sizf1fb4"; + type = "gem"; + }; + version = "1.21.0"; + }; + premailer-rails = { + dependencies = [ "actionmailer" "net-smtp" "premailer" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0004f73kgrglida336fqkgx906m6n05nnfc17mypzg5rc78iaf61"; + type = "gem"; + }; + version = "1.12.0"; + }; + private_address_check = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "05phz0vscfh9chv90yc9091pifw3cpwkh76flnhrmvja1q3na4cy"; + type = "gem"; + }; + version = "0.5.0"; + }; + public_suffix = { + groups = [ "default" "development" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0n9j7mczl15r3kwqrah09cxj8hxdfawiqxa60kga2bmxl9flfz9k"; + type = "gem"; + }; + version = "5.0.3"; + }; + puma = { + dependencies = [ "nio4r" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1x4dwx2shx0p7lsms97r85r7ji7zv57bjy3i1kmcpxc8bxvrr67c"; + type = "gem"; + }; + version = "6.3.1"; + }; + pundit = { + dependencies = [ "activesupport" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1wb03yzy1j41822rbfh9nn77im3zh1f5v8di05cd8rsrdpws542b"; + type = "gem"; + }; + version = "2.3.0"; + }; + raabro = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "10m8bln9d00dwzjil1k42i5r7l82x25ysbi45fwyv4932zsrzynl"; + type = "gem"; + }; + version = "1.4.0"; + }; + racc = { + groups = [ "default" "development" "pam_authentication" "production" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "11v3l46mwnlzlc371wr3x6yylpgafgwdf0q7hc7c1lzx6r414r5g"; + type = "gem"; + }; + version = "1.7.1"; + }; + rack = { + groups = [ "default" "development" "pam_authentication" "production" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "15rdwbyk71c9nxvd527bvb8jxkcys8r3dj3vqra5b3sa63qs30vv"; + type = "gem"; + }; + version = "2.2.8"; + }; + rack-attack = { + dependencies = [ "rack" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0z6pj5vjgl6swq7a33gssf795k958mss8gpmdb4v4cydcs7px91w"; + type = "gem"; + }; + version = "6.7.0"; + }; + rack-cors = { + dependencies = [ "rack" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "02lvkg1nb4z3zc2nry545dap7a64bb9h2k8waxfz0jkabkgnpimw"; + type = "gem"; + }; + version = "2.0.1"; + }; + rack-oauth2 = { + dependencies = [ "activesupport" "attr_required" "httpclient" "json-jwt" "rack" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1fknwsxz4429w1hndl6y30cmm2n34wmmaaj2hhp6jrm8ssfsfwjf"; + type = "gem"; + }; + version = "1.21.3"; + }; + rack-protection = { + dependencies = [ "rack" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1a12m1mv8dc0g90fs1myvis8vsgr427k1arg1q4a9qlfw6fqyhis"; + type = "gem"; + }; + version = "3.0.5"; + }; + rack-proxy = { + dependencies = [ "rack" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1a62439xwn5v6hsl9s11hdk4wj58czhcbg7lminv23mnkc0ca147"; + type = "gem"; + }; + version = "0.7.6"; + }; + rack-test = { + dependencies = [ "rack" ]; + groups = [ "default" "development" "pam_authentication" "production" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1ysx29gk9k14a14zsp5a8czys140wacvp91fja8xcja0j1hzqq8c"; + type = "gem"; + }; + version = "2.1.0"; + }; + rails = { + dependencies = [ "actioncable" "actionmailbox" "actionmailer" "actionpack" "actiontext" "actionview" "activejob" "activemodel" "activerecord" "activestorage" "activesupport" "railties" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0pxi3psfl4kpgjf6bhch1albjy9knn9c2s6sammy9lyckhh7akhq"; + type = "gem"; + }; + version = "7.0.7.2"; + }; + rails-controller-testing = { + dependencies = [ "actionpack" "actionview" "activesupport" ]; + groups = [ "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "151f303jcvs8s149mhx2g5mn67487x0blrf9dzl76q1nb7dlh53l"; + type = "gem"; + }; + version = "1.0.5"; + }; + rails-dom-testing = { + dependencies = [ "activesupport" "minitest" "nokogiri" ]; + groups = [ "default" "development" "pam_authentication" "production" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "17g05y7q7934z0ib4aph8h71c2qwjmlakkm7nb2ab45q0aqkfgjd"; + type = "gem"; + }; + version = "2.1.1"; + }; + rails-html-sanitizer = { + dependencies = [ "loofah" "nokogiri" ]; + groups = [ "default" "development" "pam_authentication" "production" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1pm4z853nyz1bhhqr7fzl44alnx4bjachcr6rh6qjj375sfz3sc6"; + type = "gem"; + }; + version = "1.6.0"; + }; + rails-i18n = { + dependencies = [ "i18n" "railties" ]; + groups = [ "default" "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1bbh5gsw46djmrgddwaq3wsjmj9rsh5dk13wkclwxf1rg9jpkn3g"; + type = "gem"; + }; + version = "7.0.7"; + }; + rails-settings-cached = { + dependencies = [ "rails" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + fetchSubmodules = false; + rev = "86328ef0bd04ce21cc0504ff5e334591e8c2ccab"; + sha256 = "06r637gimh5miq2i6ywxn9gp7nqk8n8555yw8239mykalbzda69h"; + type = "git"; + url = "https://github.com/mastodon/rails-settings-cached.git"; + }; + version = "0.6.6"; + }; + railties = { + dependencies = [ "actionpack" "activesupport" "method_source" "rake" "thor" "zeitwerk" ]; + groups = [ "default" "development" "pam_authentication" "production" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "01pdn9sn7kawwrvrbr3vz44j287xbka8mm7nrv9cl510y8gzxi2x"; + type = "gem"; + }; + version = "7.0.7.2"; + }; + rainbow = { + groups = [ "default" "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0smwg4mii0fm38pyb5fddbmrdpifwv22zv3d3px2xx497am93503"; + type = "gem"; + }; + version = "3.1.1"; + }; + rake = { + groups = [ "default" "development" "pam_authentication" "production" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "15whn7p9nrkxangbs9hh75q585yfn66lv0v2mhj6q6dl6x8bzr2w"; + type = "gem"; + }; + version = "13.0.6"; + }; + rdf = { + dependencies = [ "link_header" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1jx4xyip4inrhr099zac8ah5232g70rv39mm19p85sgpwg80a6ip"; + type = "gem"; + }; + version = "3.2.11"; + }; + rdf-normalize = { + dependencies = [ "rdf" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "12slrdq6xch5rqj1m79k1wv09264pmhs76nm300j1jsjpcfmdg0r"; + type = "gem"; + }; + version = "0.6.1"; + }; + redcarpet = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1sg9sbf9pm91l7lac7fs4silabyn0vflxwaa2x3lrzsm0ff8ilca"; + type = "gem"; + }; + version = "3.6.0"; + }; + redis = { + groups = [ "default" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0fikjg6j12ka6hh36dxzhfkpqqmilzjfzcdf59iwkzsgd63f0ziq"; + type = "gem"; + }; + version = "4.8.1"; + }; + redis-namespace = { + dependencies = [ "redis" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0f92i9cwlp6xj6fyn7qn4qsaqvxfw4wqvayll7gbd26qnai1l6p9"; + type = "gem"; + }; + version = "1.11.0"; + }; + redlock = { + dependencies = [ "redis" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0xvjwfzq7rqj4k311kidwmv5app3i7glz4miys6ixqy6c8yylz3c"; + type = "gem"; + }; + version = "1.3.2"; + }; + regexp_parser = { + groups = [ "default" "development" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "136br91alxdwh1s85z912dwz23qlhm212vy6i3wkinz3z8mkxxl3"; + type = "gem"; + }; + version = "2.8.1"; + }; + request_store = { + dependencies = [ "rack" ]; + groups = [ "default" "production" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "13ppgmsbrqah08j06bybd3cddv6dml79yzyjn7r8j1src78h98h7"; + type = "gem"; + }; + version = "1.5.1"; + }; + responders = { + dependencies = [ "actionpack" "railties" ]; + groups = [ "default" "pam_authentication" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0m9s0mkkprrz02gxhq0ijlwjy0nx1j5yrjf8ssjnhyagnx03lyrx"; + type = "gem"; + }; + version = "3.1.0"; + }; + rexml = { + groups = [ "default" "development" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "05i8518ay14kjbma550mv0jm8a6di8yp5phzrd8rj44z9qnrlrp0"; + type = "gem"; + }; + version = "3.2.6"; + }; + rotp = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "10mmzc85y7andsich586ndykw678qn1ns2wpjxrg0sc0gr4w3pig"; + type = "gem"; + }; + version = "6.2.2"; + }; + rouge = { + groups = [ "default" "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0pym2zjwl6dwdfvbn7rbvmds32r70jx9qddhvvi6pqy6987ack1v"; + type = "gem"; + }; + version = "4.1.2"; + }; + rpam2 = { + groups = [ "default" "pam_authentication" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1zvli3s4z1hf2l7gyfickm5i3afjrnycc3ihbiax6ji6arpbyf33"; + type = "gem"; + }; + version = "4.0.2"; + }; + rqrcode = { + dependencies = [ "chunky_png" "rqrcode_core" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1hggzz8i1l62pkkiybhiqv6ypxw7q844sddrrbbfczjcnj5sivi3"; + type = "gem"; + }; + version = "2.2.0"; + }; + rqrcode_core = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "06ld6386hbdhy5h0k09axmgn424kavpc8f27k1vjhknjhbf8jjfg"; + type = "gem"; + }; + version = "1.2.0"; + }; + rspec-core = { + dependencies = [ "rspec-support" ]; + groups = [ "default" "development" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0l95bnjxdabrn79hwdhn2q1n7mn26pj7y1w5660v5qi81x458nqm"; + type = "gem"; + }; + version = "3.12.2"; + }; + rspec-expectations = { + dependencies = [ "diff-lcs" "rspec-support" ]; + groups = [ "default" "development" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "05j44jfqlv7j2rpxb5vqzf9hfv7w8ba46wwgxwcwd8p0wzi1hg89"; + type = "gem"; + }; + version = "3.12.3"; + }; + rspec-mocks = { + dependencies = [ "diff-lcs" "rspec-support" ]; + groups = [ "default" "development" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1hfm17xakfvwya236graj6c2arr4sb9zasp35q5fykhyz8mhs0w2"; + type = "gem"; + }; + version = "3.12.5"; + }; + rspec-rails = { + dependencies = [ "actionpack" "activesupport" "railties" "rspec-core" "rspec-expectations" "rspec-mocks" "rspec-support" ]; + groups = [ "development" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "086qdyz7c4s5dslm6j06mq7j4jmj958whc3yinhabnqqmz7i463d"; + type = "gem"; + }; + version = "6.0.3"; + }; + rspec-sidekiq = { + dependencies = [ "rspec-core" "rspec-expectations" "rspec-mocks" "sidekiq" ]; + groups = [ "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0dijmcwjn8k6lrld3yqbqfrqb5g73l57yx98y5frx54p5qxjzbzy"; + type = "gem"; + }; + version = "4.0.1"; + }; + rspec-support = { + groups = [ "default" "development" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1ky86j3ksi26ng9ybd7j0qsdf1lpr8mzrmn98yy9gzv801fvhsgr"; + type = "gem"; + }; + version = "3.12.1"; + }; + rspec_chunked = { + groups = [ "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0h4bsj3m7vb47qnx5bry4v0xscrb3lhg1f1vyxl524znb3i2qqzv"; + type = "gem"; + }; + version = "0.6"; + }; + rubocop = { + dependencies = [ "base64" "json" "language_server-protocol" "parallel" "parser" "rainbow" "regexp_parser" "rexml" "rubocop-ast" "ruby-progressbar" "unicode-display_width" ]; + groups = [ "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1hr8g9pqw3w87a83kqcxpayrx4jmsziharrg4vqw0gr9kksx2dfv"; + type = "gem"; + }; + version = "1.56.2"; + }; + rubocop-ast = { + dependencies = [ "parser" ]; + groups = [ "default" "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "188bs225kkhrb17dsf3likdahs2p1i1sqn0pr3pvlx50g6r2mnni"; + type = "gem"; + }; + version = "1.29.0"; + }; + rubocop-capybara = { + dependencies = [ "rubocop" ]; + groups = [ "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "01fn05a87g009ch1sh00abdmgjab87i995msap26vxq1a5smdck6"; + type = "gem"; + }; + version = "2.18.0"; + }; + rubocop-factory_bot = { + dependencies = [ "rubocop" ]; + groups = [ "default" "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0kqchl8f67k2g56sq2h1sm2wb6br5gi47s877hlz94g5086f77n1"; + type = "gem"; + }; + version = "2.23.1"; + }; + rubocop-performance = { + dependencies = [ "rubocop" "rubocop-ast" ]; + groups = [ "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1v3a2g3wk3aqa0k0zzla10qkxlc625zkj3yf4zcsybs86r5bm4xn"; + type = "gem"; + }; + version = "1.19.0"; + }; + rubocop-rails = { + dependencies = [ "activesupport" "rack" "rubocop" ]; + groups = [ "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "05r46ds0dm44fb4p67hbz721zck8mdwblzssz2y25yh075hvs36j"; + type = "gem"; + }; + version = "2.20.2"; + }; + rubocop-rspec = { + dependencies = [ "rubocop" "rubocop-capybara" "rubocop-factory_bot" ]; + groups = [ "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0ylwy4afnxhbrvlaf8an9nrizj78axnzggiyfcp8v531cv8six5f"; + type = "gem"; + }; + version = "2.23.2"; + }; + ruby-prof = { + groups = [ "development" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "13fsfw43zx9pcix1fzxb95g09yadqjvc8971k74krrjz81vbyh51"; + type = "gem"; + }; + version = "1.6.3"; + }; + ruby-progressbar = { + groups = [ "default" "development" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0cwvyb7j47m7wihpfaq7rc47zwwx9k4v7iqd9s1xch5nm53rrz40"; + type = "gem"; + }; + version = "1.13.0"; + }; + ruby-saml = { + dependencies = [ "nokogiri" "rexml" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "18vnbzin5ypxrgcs9lllg7x311b69dyrdw2w1pwz84438hmxm79s"; + type = "gem"; + }; + version = "1.15.0"; + }; + ruby2_keywords = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1vz322p8n39hz3b4a9gkmz9y7a5jaz41zrm2ywf31dvkqm03glgz"; + type = "gem"; + }; + version = "0.0.5"; + }; + rubyzip = { + groups = [ "default" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0grps9197qyxakbpw02pda59v45lfgbgiyw48i0mq9f2bn9y6mrz"; + type = "gem"; + }; + version = "2.3.2"; + }; + rufus-scheduler = { + dependencies = [ "fugit" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "14lr8c2sswn0sisvrfi4448pmr34za279k3zlxgh581rl1y0gjjz"; + type = "gem"; + }; + version = "3.9.1"; + }; + safety_net_attestation = { + dependencies = [ "jwt" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1khq0y5w7lf2b9a220298hphf3pakd216jc9a4x4a9pdwxs2vgln"; + type = "gem"; + }; + version = "0.4.0"; + }; + sanitize = { + dependencies = [ "crass" "nokogiri" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1kymrjdpbmn4yaml3aaqyj1dzj8gqmm9h030dc2rj5mvja7fpi28"; + type = "gem"; + }; + version = "6.0.2"; + }; + scenic = { + dependencies = [ "activerecord" "railties" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "04sd4jmgnwpilr3k061x87yyryya2mj15a8602fip49lfxza5548"; + type = "gem"; + }; + version = "1.7.0"; + }; + selenium-webdriver = { + dependencies = [ "rexml" "rubyzip" "websocket" ]; + groups = [ "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0ws0mh230l1pvyxcrlcr48w01alfhprjs1jbd8yrn463drsr2yac"; + type = "gem"; + }; + version = "4.11.0"; + }; + semantic_range = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1dlp97vg95plrsaaqj7x8l7z9vsjbhnqk4rw1l30gy26lmxpfrih"; + type = "gem"; + }; + version = "3.0.0"; + }; + sidekiq = { + dependencies = [ "connection_pool" "rack" "redis" ]; + groups = [ "default" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0iv7vgqyrpymiwvc3ca24sl4lda8m627p657p0v4xzdpzincrnbr"; + type = "gem"; + }; + version = "6.5.9"; + }; + sidekiq-bulk = { + dependencies = [ "sidekiq" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "08nyxzmgf742irafy3l4fj09d4s5pyvsh0dzlh8y4hl51rgkh4xv"; + type = "gem"; + }; + version = "0.2.0"; + }; + sidekiq-scheduler = { + dependencies = [ "rufus-scheduler" "sidekiq" "tilt" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0p5jjs3x2pa2fy494xs39xbq642pri13809dcr1l3hjsm56qvp1h"; + type = "gem"; + }; + version = "5.0.3"; + }; + sidekiq-unique-jobs = { + dependencies = [ "brpoplpush-redis_script" "concurrent-ruby" "redis" "sidekiq" "thor" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "02f91b24hrrn688wqvxb13lwvcgqb7g9k3sxylnydd6v89wr8mcg"; + type = "gem"; + }; + version = "7.1.29"; + }; + simple-navigation = { + dependencies = [ "activesupport" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1wc1rapwhqymcjfxmlgam4cvbyhnzfxada2damq88ij2p77pjz4q"; + type = "gem"; + }; + version = "4.4.0"; + }; + simple_form = { + dependencies = [ "actionpack" "activemodel" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0z4df65w9qpri315lpvzazdxa9xb7yj0j3d77q06wf0jnpvw4mzs"; + type = "gem"; + }; + version = "5.2.0"; + }; + simplecov = { + dependencies = [ "docile" "simplecov-html" "simplecov_json_formatter" ]; + groups = [ "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "198kcbrjxhhzca19yrdcd6jjj9sb51aaic3b0sc3pwjghg3j49py"; + type = "gem"; + }; + version = "0.22.0"; + }; + simplecov-html = { + groups = [ "default" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0yx01bxa8pbf9ip4hagqkp5m0mqfnwnw2xk8kjraiywz4lrss6jb"; + type = "gem"; + }; + version = "0.12.3"; + }; + simplecov_json_formatter = { + groups = [ "default" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0a5l0733hj7sk51j81ykfmlk2vd5vaijlq9d5fn165yyx3xii52j"; + type = "gem"; + }; + version = "0.1.4"; + }; + smart_properties = { + groups = [ "default" "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0jrqssk9qhwrpq41arm712226vpcr458xv6xaqbk8cp94a0kycpr"; + type = "gem"; + }; + version = "1.17.0"; + }; + sprockets = { + dependencies = [ "concurrent-ruby" "rack" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "182jw5a0fbqah5w9jancvfmjbk88h8bxdbwnl4d3q809rpxdg8ay"; + type = "gem"; + }; + version = "3.7.2"; + }; + sprockets-rails = { + dependencies = [ "actionpack" "activesupport" "sprockets" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1b9i14qb27zs56hlcc2hf139l0ghbqnjpmfi0054dxycaxvk5min"; + type = "gem"; + }; + version = "3.4.2"; + }; + sshkit = { + dependencies = [ "net-scp" "net-ssh" ]; + groups = [ "default" "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "14a717mr2cmpgld5fcdd124cvlc5b634f96rhwlnmmc4m8bbkcp9"; + type = "gem"; + }; + version = "1.21.5"; + }; + stackprof = { + groups = [ "development" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0bhdgfb0pmw9mav1kw9fn0ka012sa0i3h5ppvqssw5xq48nhxnr8"; + type = "gem"; + }; + version = "0.2.25"; + }; + statsd-ruby = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "028136c463nbravckxb1qi5c5nnv9r6vh2cyhiry423lac4xz79n"; + type = "gem"; + }; + version = "1.5.0"; + }; + stoplight = { + dependencies = [ "redlock" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1vhqx7q8qpq3x9ba504n7bp0r9dxcck0r0hd73cac2iqkix6khlv"; + type = "gem"; + }; + version = "3.0.2"; + }; + strong_migrations = { + dependencies = [ "activerecord" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0wz4zhsp4xia8zcpi98v4sgjlv2prd515l8jz4f7j0wk45dfkjs1"; + type = "gem"; + }; + version = "0.8.0"; + }; + swd = { + dependencies = [ "activesupport" "attr_required" "httpclient" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "12b3q2sw42nnilfb51nlqdv07f31vdv2j595kd99asnkw4cjlf5w"; + type = "gem"; + }; + version = "1.3.0"; + }; + sysexits = { + groups = [ "default" "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0qjng6pllznmprzx8vb0zg0c86hdrkyjs615q41s9fjpmv2430jr"; + type = "gem"; + }; + version = "1.2.0"; + }; + temple = { + groups = [ "default" "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "09p32vp94sa1mbr0if0adf02yzc4ns00lsmpwns2xbkncwpzrqm4"; + type = "gem"; + }; + version = "0.10.2"; + }; + terminal-table = { + dependencies = [ "unicode-display_width" ]; + groups = [ "default" "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "14dfmfjppmng5hwj7c5ka6qdapawm3h6k9lhn8zj001ybypvclgr"; + type = "gem"; + }; + version = "3.0.2"; + }; + terrapin = { + dependencies = [ "climate_control" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0p18f05r0c5s70571gqig3z2ym74wx79s6rd45sprp207bqskzn9"; + type = "gem"; + }; + version = "0.6.0"; + }; + test-prof = { + groups = [ "development" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "08j5456rdpgxvv8bs44x81jrxzpxb79wxfxdq4fqwxyircxzi2jj"; + type = "gem"; + }; + version = "1.2.2"; + }; + thor = { + groups = [ "default" "development" "pam_authentication" "production" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0k7j2wn14h1pl4smibasw0bp66kg626drxb59z7rzflch99cd4rg"; + type = "gem"; + }; + version = "1.2.2"; + }; + tilt = { + groups = [ "default" "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0bmjgbv8158klwp2r3klxjwaj93nh1sbl4xvj9wsha0ic478avz7"; + type = "gem"; + }; + version = "2.2.0"; + }; + timeout = { + groups = [ "default" "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1d9cvm0f4zdpwa795v3zv4973y5zk59j7s1x3yn90jjrhcz1yvfd"; + type = "gem"; + }; + version = "0.4.0"; + }; + tpm-key_attestation = { + dependencies = [ "bindata" "openssl" "openssl-signature_algorithm" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0v8y5dibsyskv1ncdgszhxwzq0gzmvb0zl7sgmx0xvsgy86dhcz1"; + type = "gem"; + }; + version = "0.12.0"; + }; + tty-color = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0aik4kmhwwrmkysha7qibi2nyzb4c8kp42bd5vxnf8sf7b53g73g"; + type = "gem"; + }; + version = "0.6.0"; + }; + tty-cursor = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0j5zw041jgkmn605ya1zc151bxgxl6v192v2i26qhxx7ws2l2lvr"; + type = "gem"; + }; + version = "0.7.1"; + }; + tty-prompt = { + dependencies = [ "pastel" "tty-reader" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1j4y8ik82azjxshgd4i1v4wwhsv3g9cngpygxqkkz69qaa8cxnzw"; + type = "gem"; + }; + version = "0.23.1"; + }; + tty-reader = { + dependencies = [ "tty-cursor" "tty-screen" "wisper" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1cf2k7w7d84hshg4kzrjvk9pkyc2g1m3nx2n1rpmdcf0hp4p4af6"; + type = "gem"; + }; + version = "0.9.0"; + }; + tty-screen = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "18jr6s1cg8yb26wzkqa6874q0z93rq0y5aw092kdqazk71y6a235"; + type = "gem"; + }; + version = "0.8.1"; + }; + twitter-text = { + dependencies = [ "idn-ruby" "unf" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1dnmp0bj3l01nbb52zby2c7hrazcdwfg846knkrjdfl0yfmv793z"; + type = "gem"; + }; + version = "3.1.0"; + }; + tzinfo = { + dependencies = [ "concurrent-ruby" ]; + groups = [ "default" "development" "pam_authentication" "production" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "16w2g84dzaf3z13gxyzlzbf748kylk5bdgg3n1ipvkvvqy685bwd"; + type = "gem"; + }; + version = "2.0.6"; + }; + tzinfo-data = { + dependencies = [ "tzinfo" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0m2d0gpsgqnv29j5h2d6g57g0rayvd460b8s2vjr8sn46bqf89m5"; + type = "gem"; + }; + version = "1.2023.3"; + }; + unf = { + dependencies = [ "unf_ext" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0bh2cf73i2ffh4fcpdn9ir4mhq8zi50ik0zqa1braahzadx536a9"; + type = "gem"; + }; + version = "0.1.4"; + }; + unf_ext = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1yj2nz2l101vr1x9w2k83a0fag1xgnmjwp8w8rw4ik2rwcz65fch"; + type = "gem"; + }; + version = "0.0.8.2"; + }; + unicode-display_width = { + groups = [ "default" "development" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1gi82k102q7bkmfi7ggn9ciypn897ylln1jk9q67kjhr39fj043a"; + type = "gem"; + }; + version = "2.4.2"; + }; + uri = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0fa49cdssxllj1j37a56kq27wsibx5lmqxkqdk1rz3452y0bsydy"; + type = "gem"; + }; + version = "0.12.2"; + }; + validate_email = { + dependencies = [ "activemodel" "mail" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1r1fz29l699arka177c9xw7409d1a3ff95bf7a6pmc97slb91zlx"; + type = "gem"; + }; + version = "0.1.6"; + }; + validate_url = { + dependencies = [ "activemodel" "public_suffix" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0lblym140w5n88ijyfgcvkxvpfj8m6z00rxxf2ckmmhk0x61dzkj"; + type = "gem"; + }; + version = "1.0.15"; + }; + warden = { + dependencies = [ "rack" ]; + groups = [ "default" "pam_authentication" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1l7gl7vms023w4clg02pm4ky9j12la2vzsixi2xrv9imbn44ys26"; + type = "gem"; + }; + version = "1.2.9"; + }; + webauthn = { + dependencies = [ "android_key_attestation" "awrence" "bindata" "cbor" "cose" "openssl" "safety_net_attestation" "tpm-key_attestation" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1ri09bf640kkw4v6k2g90q2nw1mx2hsghhngaqgb7958q8id8xrz"; + type = "gem"; + }; + version = "3.0.0"; + }; + webfinger = { + dependencies = [ "activesupport" "httpclient" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "18jj50b44a471ig7hw1ax90wxaaz40acmrf6cm7m2iyshlffy53q"; + type = "gem"; + }; + version = "1.2.0"; + }; + webmock = { + dependencies = [ "addressable" "crack" "hashdiff" ]; + groups = [ "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0vfispr7wd2p1fs9ckn1qnby1yyp4i1dl7qz8n482iw977iyxrza"; + type = "gem"; + }; + version = "3.19.1"; + }; + webpacker = { + dependencies = [ "activesupport" "rack-proxy" "railties" "semantic_range" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0fh4vijqiq1h7w28llk67y9csc0m4wkdivrsl4fsxg279v6j5z3i"; + type = "gem"; + }; + version = "5.4.4"; + }; + webpush = { + dependencies = [ "hkdf" "jwt" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + fetchSubmodules = false; + rev = "f14a4d52e201128b1b00245d11b6de80d6cfdcd9"; + sha256 = "1gz34809xwyaqprxmjdyvzsxc63rdnmxn8w44iqkhpi3dzmkacmp"; + type = "git"; + url = "https://github.com/ClearlyClaire/webpush.git"; + }; + version = "0.3.8"; + }; + websocket = { + groups = [ "default" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0dib6p55sl606qb4vpwrvj5wh881kk4aqn2zpfapf8ckx7g14jw8"; + type = "gem"; + }; + version = "1.2.9"; + }; + websocket-driver = { + dependencies = [ "websocket-extensions" ]; + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1nyh873w4lvahcl8kzbjfca26656d5c6z3md4sbqg5y1gfz0157n"; + type = "gem"; + }; + version = "0.7.6"; + }; + websocket-extensions = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0hc2g9qps8lmhibl5baa91b4qx8wqw872rgwagml78ydj8qacsqw"; + type = "gem"; + }; + version = "0.1.5"; + }; + wisper = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1rpsi0ziy78cj82sbyyywby4d0aw0a5q84v65qd28vqn79fbq5yf"; + type = "gem"; + }; + version = "2.0.1"; + }; + xorcist = { + groups = [ "default" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1dbbiy8xlcfvn9ais37xfb5rci4liwakkmxzbkp72wmvlgcrf339"; + type = "gem"; + }; + version = "1.1.3"; + }; + xpath = { + dependencies = [ "nokogiri" ]; + groups = [ "default" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "0bh8lk9hvlpn7vmi6h4hkcwjzvs2y0cmkk3yjjdr8fxvj6fsgzbd"; + type = "gem"; + }; + version = "3.2.0"; + }; + zeitwerk = { + groups = [ "default" "development" "pam_authentication" "production" "test" ]; + platforms = [ ]; + source = { + remotes = [ "https://rubygems.org" ]; + sha256 = "1mwdd445w63khz13hpv17m2br5xngyjl3jdj08xizjbm78i2zrxd"; + type = "gem"; + }; + version = "2.6.11"; + }; +} + diff --git a/nixos/pkgs/glitch-soc/source.nix b/nixos/pkgs/glitch-soc/source.nix new file mode 100644 index 00000000..9f67c32e --- /dev/null +++ b/nixos/pkgs/glitch-soc/source.nix @@ -0,0 +1,13 @@ +# This file was generated by pkgs.mastodon.updateScript. +{ fetchgit, applyPatches }: +let + src = fetchgit { + url = "https://github.com/glitch-soc/mastodon.git"; + rev = "a1df9fdb06854bd55f018918236132ccfa7d9d84"; + sha256 = "0amqiigq3qgag6qm119aaysmd2k93vwgr1aynxjxmbpn35ykcay3"; + }; +in +applyPatches { + inherit src; + patches = [ ]; +} diff --git a/nixos/pkgs/glitch-soc/update.nix b/nixos/pkgs/glitch-soc/update.nix new file mode 100644 index 00000000..a4318e7c --- /dev/null +++ b/nixos/pkgs/glitch-soc/update.nix @@ -0,0 +1,38 @@ +{ runCommand +, lib +, makeWrapper +, yarn2nix +, bundix +, coreutils +, diffutils +, nix-prefetch-git +, gnused +, jq +}: +let + binPath = lib.makeBinPath [ + yarn2nix + bundix + coreutils + diffutils + nix-prefetch-git + gnused + jq + ]; +in +runCommand "mastodon-update-script" +{ + nativeBuildInputs = [ makeWrapper ]; + + meta = { + maintainers = with lib.maintainers; [ happy-river ]; + description = + "Utility to generate Nix expressions for Mastodon's dependencies"; + platforms = lib.platforms.unix; + }; +} '' + mkdir -p $out/bin + cp ${./update.sh} $out/bin/update.sh + patchShebangs $out/bin/update.sh + wrapProgram $out/bin/update.sh --prefix PATH : ${binPath} +'' diff --git a/nixos/pkgs/glitch-soc/update.sh b/nixos/pkgs/glitch-soc/update.sh new file mode 100755 index 00000000..3a0686a7 --- /dev/null +++ b/nixos/pkgs/glitch-soc/update.sh @@ -0,0 +1,98 @@ +#!/usr/bin/env bash +set -e + +URL=https://github.com/mastodon/mastodon.git + +POSITIONAL=() +while [[ $# -gt 0 ]]; do + key="$1" + + case $key in + --url) + URL="$2" + shift # past argument + shift # past value + ;; + --ver) + VERSION="$2" + shift # past argument + shift # past value + ;; + --rev) + REVISION="$2" + shift # past argument + shift # past value + ;; + --patches) + PATCHES="$2" + shift # past argument + shift # past value + ;; + *) # unknown option + POSITIONAL+=("$1") + shift # past argument + ;; + esac +done + +if [[ -z "$VERSION" || -n "$POSITIONAL" ]]; then + echo "Usage: update.sh [--url URL] --ver VERSION [--rev REVISION] [--patches PATCHES]" + echo "URL may be any path acceptable to 'git clone' and VERSION the" + echo "semantic version number. If VERSION is not a revision acceptable to" + echo "'git checkout', you must provide one in REVISION. If URL is not" + echo "provided, it defaults to https://github.com/mastodon/mastodon.git." + echo "PATCHES, if provided, should be one or more Nix expressions" + echo "separated by spaces." + exit 1 +fi + +if [[ -z "$REVISION" ]]; then + REVISION="$VERSION" +fi + +rm -f gemset.nix version.nix source.nix +TARGET_DIR="$PWD" + + +WORK_DIR=$(mktemp -d) + +# Check that working directory was created. +if [[ ! "$WORK_DIR" || ! -d "$WORK_DIR" ]]; then + echo "Could not create temporary directory" + exit 1 +fi + +# Delete the working directory on exit. +function cleanup { + # Report errors, if any, from nix-prefetch-git + grep "fatal" $WORK_DIR/nix-prefetch-git.out >/dev/stderr || true + rm -rf "$WORK_DIR" +} +trap cleanup EXIT + +echo "Fetching source code $REVISION from $URL" +JSON=$(nix-prefetch-git --url "$URL" --rev "$REVISION" 2> $WORK_DIR/nix-prefetch-git.out) +SHA=$(echo $JSON | jq -r .sha256) +FETCHED_SOURCE_DIR=$(grep '^path is' $WORK_DIR/nix-prefetch-git.out | sed 's/^path is //') + +echo "Creating version.nix" +echo \"$VERSION\" | sed 's/^"v/"/' > version.nix + +cat > source.nix << EOF +# This file was generated by pkgs.mastodon.updateScript. +{ fetchgit, applyPatches }: let + src = fetchgit { + url = "$URL"; + rev = "$REVISION"; + sha256 = "$SHA"; + }; +in applyPatches { + inherit src; + patches = [$PATCHES]; +} +EOF +SOURCE_DIR="$(nix-build --no-out-link -E '(import {}).callPackage ./source.nix {}')" + +echo "Creating gemset.nix" +bundix --lockfile="$SOURCE_DIR/Gemfile.lock" --gemfile="$SOURCE_DIR/Gemfile" +echo "" >> $TARGET_DIR/gemset.nix # Create trailing newline to please EditorConfig checks diff --git a/nixos/pkgs/glitch-soc/version.nix b/nixos/pkgs/glitch-soc/version.nix new file mode 100644 index 00000000..2d0483ea --- /dev/null +++ b/nixos/pkgs/glitch-soc/version.nix @@ -0,0 +1 @@ +"4.1.7" diff --git a/nixos/pkgs/plex-pass/default.nix b/nixos/pkgs/plex-pass/default.nix new file mode 100644 index 00000000..a2c93c7c --- /dev/null +++ b/nixos/pkgs/plex-pass/default.nix @@ -0,0 +1,3 @@ +{ plex, plexRaw-plexpass }: +# Copied from: https://github.com/tadfisher/flake/blob/ed949a619236ba30f0be614fed804abdf1e8005b/pkgs/plex-plexpass/default.nix +plex.override { plexRaw = plexRaw-plexpass; } diff --git a/nixos/pkgs/plex-pass/raw.nix b/nixos/pkgs/plex-pass/raw.nix new file mode 100644 index 00000000..425928b0 --- /dev/null +++ b/nixos/pkgs/plex-pass/raw.nix @@ -0,0 +1,15 @@ +{ lib, stdenv, plexRaw, fetchurl }: +let + sources = builtins.fromJSON (builtins.readFile ./sources.json); + source = lib.findFirst (x: x.platform == stdenv.hostPlatform.system) + (throw "unsupported platform: ${stdenv.hostPlatform.system}") + sources; +in +plexRaw.overrideAttrs (attrs: { + pname = attrs.pname + "-plexpass"; + inherit (source) version; + src = fetchurl { + inherit (source) url; + sha256 = source.hash; + }; +}) diff --git a/nixos/pkgs/plex-pass/sources.json b/nixos/pkgs/plex-pass/sources.json new file mode 100644 index 00000000..ad6acea4 --- /dev/null +++ b/nixos/pkgs/plex-pass/sources.json @@ -0,0 +1,14 @@ +[ + { + "version": "1.32.8.7639", + "platform": "aarch64-linux", + "url": "https://downloads.plex.tv/plex-media-server-new/1.32.8.7639-fb6452ebf/debian/plexmediaserver_1.32.8.7639-fb6452ebf_arm64.deb", + "hash": "1drfqcjlp4qyy47wy7mjwxi36c8q3dly0nmzgjbnl8b0v7jmpldz" + }, + { + "version": "1.32.8.7639", + "platform": "x86_64-linux", + "url": "https://downloads.plex.tv/plex-media-server-new/1.32.8.7639-fb6452ebf/debian/plexmediaserver_1.32.8.7639-fb6452ebf_amd64.deb", + "hash": "1jzxfjjislfwmr9jyjvh4iy5p9kl7af47hpx9kqlivp6vc0rblcd" + } +] diff --git a/nixos/pkgs/plex-pass/update.sh b/nixos/pkgs/plex-pass/update.sh new file mode 100755 index 00000000..bead2f32 --- /dev/null +++ b/nixos/pkgs/plex-pass/update.sh @@ -0,0 +1,33 @@ +#! /usr/bin/env nix-shell +#! nix-shell -i bash -p vault curl jq + +shopt -s extglob +set -eu -o pipefail + +path="$(realpath "$(dirname "$0")")" + +declare -A platforms=( + [linux-x86_64]=x86_64-linux + [linux-aarch64]=aarch64-linux +) + +token=$(vault kv get -field=plex_token hades_secrets/nixos/plex) +manifest=$(curl -s "https://plex.tv/api/downloads/5.json?channel=plexpass" -H "X-Plex-Token: ${token}") +version=$(echo "$manifest" | jq -r '.computer.Linux.version | split("-") | .[0]') + +tmp="$path/sources.tmp.json" +echo '' >$tmp + +for arch in "${!platforms[@]}"; do + url="$(echo "$manifest" | jq --arg arch "$arch" -r '.computer.Linux.releases[] | select(.distro == "debian" and .build == $arch) .url')" + hash="$(nix-prefetch-url "$url")" + nixPlatform=${platforms[$arch]} + jq --arg version $version \ + --arg platform $nixPlatform \ + --arg url "$url" \ + --arg hash $hash \ + -n '$ARGS.named' >>$tmp +done + +jq -s '.' $tmp >"$path/sources.json" +rm $tmp diff --git a/nixos/pkgs/roundcube-swipe/default.nix b/nixos/pkgs/roundcube-swipe/default.nix new file mode 100644 index 00000000..50aeb281 --- /dev/null +++ b/nixos/pkgs/roundcube-swipe/default.nix @@ -0,0 +1,20 @@ +{ runCommand, fetchFromGitHub }: +let + roundcubePlugin = { version, src, ... }: + + runCommand "roundcube-plugin-swipe-${version}" { } '' + mkdir -p $out/plugins/ + cp -r ${src} $out/plugins/swipe + ''; +in +roundcubePlugin rec { + pname = "roundcube-swipe"; + version = "0.5"; + + src = fetchFromGitHub { + owner = "johndoh"; + repo = pname; + rev = "de96f82183bc593d879c335e6614fa983d51abfc"; + sha256 = "sha256-vrMSvGwUzufSFDsUvUSL9JLR/+GtWdebVqgKiXMOOq4="; + }; +} diff --git a/nixos/pkgs/vscode-extensions/platformio.nix b/nixos/pkgs/vscode-extensions/platformio.nix new file mode 100644 index 00000000..90367dcc --- /dev/null +++ b/nixos/pkgs/vscode-extensions/platformio.nix @@ -0,0 +1,11 @@ +{ vscode-utils }: +let inherit (vscode-utils) buildVscodeMarketplaceExtension; +in buildVscodeMarketplaceExtension { + mktplcRef = { + name = "platformio-ide"; + publisher = "platformio"; + version = "3.1.1"; + sha256 = "sha256-g9yTG3DjVUS2w9eHGAai5LoIfEGus+FPhqDnCi4e90Q="; + # sha256 = lib.fakeSha256; + }; +} diff --git a/nixos/templates/proxmox-lxc.nix b/nixos/templates/proxmox-lxc.nix new file mode 100644 index 00000000..74079ddf --- /dev/null +++ b/nixos/templates/proxmox-lxc.nix @@ -0,0 +1,27 @@ +{ lib, ... }: { + imports = [ ../common ../common/generic-lxc.nix ]; + + proxmoxLXC = { + manageNetwork = true; + manageHostName = true; + privileged = false; + }; + + # Enable SSH + services.openssh = { + enable = true; + settings = { + PasswordAuthentication = true; + PermitRootLogin = "yes"; + }; + openFirewall = true; + }; + + networking.hostName = lib.mkDefault "template"; + + time.timeZone = lib.mkDefault "Europe/Amsterdam"; + + system.stateVersion = "23.05"; + + users.users.root.initialPassword = "toor"; +} diff --git a/nixos/templates/proxmox-vm.nix b/nixos/templates/proxmox-vm.nix new file mode 100644 index 00000000..567090f3 --- /dev/null +++ b/nixos/templates/proxmox-vm.nix @@ -0,0 +1,30 @@ +{ lib, ... }: { + imports = [ ../common/common.nix ../common/generic-vm.nix ]; + + proxmox.qemuConf = { + virtio0 = "local-zfs:vm-9999-disk-0"; + cores = 1; + memory = 1024; + bios = "ovmf"; + }; + + # Enable SSH + services.openssh = { + enable = true; + settings = { + PasswordAuthentication = true; + PermitRootLogin = "yes"; + }; + openFirewall = true; + }; + + networking.hostName = lib.mkDefault "template"; + + time.timeZone = lib.mkDefault "Europe/Amsterdam"; + + networking.useDHCP = true; + + system.stateVersion = "23.05"; + + users.users.root.initialPassword = "toor"; +} diff --git a/nixos/util.nix b/nixos/util.nix new file mode 100644 index 00000000..5a55aa5e --- /dev/null +++ b/nixos/util.nix @@ -0,0 +1,87 @@ +{ nixpkgs, home-manager, mailserver, lanzaboote, attic, ... }: +let + inherit (builtins) filter attrValues concatMap mapAttrs; + inherit (nixpkgs.lib.attrsets) mapAttrsToList; + base_imports = [ + home-manager.nixosModules.home-manager + mailserver.nixosModules.mailserver + attic.nixosModules.atticd + ]; + type_import = + let + import_cases = { + "lxc" = [ + "${nixpkgs}/nixos/modules/virtualisation/lxc-container.nix" + ./common/generic-lxc.nix + ]; + "vm" = [ ./common/generic-vm.nix ]; + "local" = [ + lanzaboote.nixosModules.lanzaboote + ./common/desktop + ]; + }; + in + type: import_cases.${type} ++ base_imports; + # Helper function to resolve what should be imported depending on the type of config (lxc, vm, bare metal) + resolve_imports = { hostname, realm, profile ? hostname, type ? "lxc", ... }: + type_import type + ++ [ ./common "${./.}/hosts/${realm}/${profile}/configuration.nix" ]; + + # Add to whatever realm a host belong to its list of tags + add_realm_to_tags = mapAttrs (realm: + mapAttrs (_hostname: + { type ? "lxc", tags ? [ ], ... }@host: + host // { + # Tags are for deployment, so don't add them to local machines + tags = tags ++ (if type == "local" then [ ] else [ realm ]); + inherit realm; + })); + + # Flatten all hosts to a single list + flatten_hosts = realms: + concatMap (mapAttrsToList (name: value: value // { hostname = name; })) + (attrValues realms); + + # Filter out all hosts which aren't nixos + filter_nix_hosts = filter ({ nix ? true, ... }: nix); + + # outputs + + # Helper function to build a colmena host definition + mkColmenaHost = + { ip ? null + , exposes ? null + , hostname + , tags + , realm + , type ? "lxc" + , ... + }@host: + let + # this makes local apply work a bit nicer + name = if type == "local" then hostname else "${hostname}.${realm}"; + in + { + "${name}" = { + imports = resolve_imports host; + networking = { + hostName = hostname; + domain = realm; + }; + meta = { + inherit exposes; + ipv4 = ip; + }; + deployment = { + inherit tags; + targetHost = ip; + allowLocalDeployment = type == "local"; + targetUser = null; # Defaults to $USER + }; + }; + }; + hosts = add_realm_to_tags (import ./hosts); + flat_hosts = flatten_hosts hosts; + nixHosts = filter_nix_hosts flat_hosts; +in +{ inherit base_imports mkColmenaHost hosts flat_hosts nixHosts; } diff --git a/notes/boot_full.md b/notes/boot_full.md new file mode 100644 index 00000000..05ef3363 --- /dev/null +++ b/notes/boot_full.md @@ -0,0 +1,11 @@ +# NixOS /boot full + +If `/boot` is full run the following commands: + +``` +sudo nix-collect-garbage -d +nix-env -p /mnt/nix/var/nix/profiles/system --delete-generations +2 +sudo nixos-rebuild boot --flake '.#eevee' +``` + +This should delete the older generations and free up some space diff --git a/notes/ideas.md b/notes/ideas.md new file mode 100644 index 00000000..0318c1c7 --- /dev/null +++ b/notes/ideas.md @@ -0,0 +1,32 @@ +# 1. Add port info to hosts +Re-use `hosts` setup and add domain and port information to each host +```nix +"overseerr" = { + ip = "192.168.0.105"; + mac = "8E:21:7F:88:3A:83"; + # new stuff + exposes = { + requests = { + domain = "requests.xirion.net"; + port = 3000; + }; + ... + }; +} +``` +which then can get translated to nginx config: +```nix +virtualHosts."requests.xirion.net" = proxy "http://192.168.0.105:80"; +``` + +Ideally hosts should also be able to access their own host information more easily so +that in service config one could use `thisHost.exposes.requests.port` or similar, +and the firewall can automatically be opened + +# 2. Authoritative nameserver +Using the definitions from (1), we can then also build authoritative DNS records +by folding over `hosts[i].exposes.requests.domain` and collating that with its realm (and therefore external IP) + +This also means I should probably put the external IP in some kind of meta block per realm. + +[dns.nix](https://github.com/kirelagin/dns.nix) seems to be a nice DSL for DNS stuff diff --git a/renovate.json b/renovate.json new file mode 100644 index 00000000..7190a60b --- /dev/null +++ b/renovate.json @@ -0,0 +1,3 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json" +} diff --git a/repl.nix b/repl.nix new file mode 100644 index 00000000..71413191 --- /dev/null +++ b/repl.nix @@ -0,0 +1,7 @@ +let + flake = builtins.getFlake (toString ./.); + nixpkgs = import { }; +in +{ + inherit flake; +} // flake // builtins // nixpkgs // nixpkgs.lib // flake.nixosConfigurations