├── .github ├── CODEOWNERS ├── labeler.yml ├── funding.yml ├── contributing.md ├── security.md ├── ISSUE_TEMPLATE │ ├── config.yml │ ├── fr.yml │ └── bug.yml ├── workflows │ ├── transfer.yml │ ├── label.yml │ ├── helm-docs.yml │ ├── lint-and-release.yml │ └── cleanup.yml ├── support.md ├── pull_request_template.md └── code_of_conduct.md ├── ct.yaml ├── .gitignore ├── charts ├── firefly-iii │ ├── templates │ │ ├── secret-app-key.yaml │ │ ├── secret.yaml │ │ ├── service.yaml │ │ ├── configmap.yaml │ │ ├── pvc.yaml │ │ ├── hpa.yaml │ │ ├── ingress.yaml │ │ ├── _helpers.tpl │ │ ├── cronjob.yaml │ │ └── deployment.yaml │ ├── .helmignore │ ├── Chart.yaml │ ├── README.md.gotmpl │ ├── values.yaml │ └── README.md ├── firefly-db │ ├── Chart.yaml │ ├── .helmignore │ ├── templates │ │ ├── firefly-db-svc.yml │ │ ├── firefly-db-cm.yml │ │ ├── firefly-db-cron-backup.yml │ │ ├── firefly-db-pvc.yml │ │ ├── firefly-backup-pvc.yml │ │ ├── firefly-db-backup-job.yml │ │ ├── _helpers.tpl │ │ ├── backup.tpl │ │ ├── firefly-db-deploy.yml │ │ └── firefly-db-restore-job.yml │ ├── README.md.gotmpl │ ├── values.yaml │ ├── Makefile │ └── README.md ├── importer │ ├── templates │ │ ├── secret.yaml │ │ ├── configmap.yaml │ │ ├── secret-files.yaml │ │ ├── service.yaml │ │ ├── ingress.yaml │ │ ├── _helpers.tpl │ │ └── deployment.yaml │ ├── Chart.yaml │ ├── .helmignore │ ├── README.md.gotmpl │ ├── values.yaml │ └── README.md ├── firefly-iii-stack │ ├── .helmignore │ ├── Chart.yaml │ ├── values.yaml │ ├── README.md.gotmpl │ └── README.md └── README.md ├── kustomize ├── kustomization.yaml ├── pv-firefly-iii.yaml.example ├── pv-firefly-iii-mysql.yaml.example ├── ingress-firefly-iii.yaml ├── ingress-firefly-iii-importer.yaml ├── ingress-firefly-iii-cron.yaml ├── firefly-iii-importer.yaml ├── mysql.yaml └── firefly-iii.yaml ├── helm └── README.md ├── .devcontainer ├── library-scripts │ ├── govc-completion.sh │ ├── copy-kube-config.sh │ └── docker-debian.sh ├── devcontainer.json ├── README.md └── Dockerfile ├── readme.md └── license /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # @JC5 is code owner for everything 2 | * @JC5 3 | -------------------------------------------------------------------------------- /.github/labeler.yml: -------------------------------------------------------------------------------- 1 | # Add 'move' label to any issue that gets opened 2 | move: 3 | - '/.*/' 4 | -------------------------------------------------------------------------------- /.github/funding.yml: -------------------------------------------------------------------------------- 1 | # Firefly III sponsor options 2 | 3 | github: jc5 4 | patreon: JC5 5 | ko_fi: jamesc5 6 | liberapay: JC5 7 | -------------------------------------------------------------------------------- /ct.yaml: -------------------------------------------------------------------------------- 1 | # See https://github.com/helm/chart-testing#configuration 2 | remote: origin 3 | target-branch: main 4 | chart-dirs: 5 | - charts 6 | -------------------------------------------------------------------------------- /.github/contributing.md: -------------------------------------------------------------------------------- 1 | # [Contributing guidelines](https://docs.firefly-iii.org/other-pages/contributing) 2 | 3 | [Contributing guidelines](https://docs.firefly-iii.org/other-pages/contributing) -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Helm packages 2 | *.tgz 3 | 4 | # Helm chart lock files - those would need manual updates. 5 | # As we have all charts in the same repository, we can assume trust between them 6 | Chart.lock 7 | 8 | .idea 9 | -------------------------------------------------------------------------------- /charts/firefly-iii/templates/secret-app-key.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: {{ include "firefly-iii.fullname" . }}-app-key 5 | labels: 6 | {{- include "firefly-iii.labels" . | nindent 4 }} 7 | data: 8 | APP_KEY: {{ include "firefly-iii.app-key" . | b64enc | quote }} 9 | -------------------------------------------------------------------------------- /charts/firefly-db/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: firefly-db 3 | description: Installs a postgres db for Firefly III 4 | type: application 5 | version: 0.2.9 6 | sources: 7 | - https://github.com/firefly-iii/kubernetes/tree/main/charts/firefly-db 8 | maintainers: 9 | - name: morremeyer 10 | email: firefly-iii@mor.re 11 | -------------------------------------------------------------------------------- /.github/security.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | The Security Policy for the software and/or documentation in this repository is equal to the [Security Policy](https://github.com/firefly-iii/firefly-iii/security/policy) of [Firefly III](https://github.com/firefly-iii/firefly-iii) itself. 4 | 5 | * https://github.com/firefly-iii/firefly-iii/security/policy 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Ask a question 4 | url: https://github.com/firefly-iii/firefly-iii/discussions 5 | about: Please ask and answer questions here. 6 | - name: I need support! 7 | url: https://github.com/firefly-iii/firefly-iii/discussions 8 | about: I think I broke something... 9 | -------------------------------------------------------------------------------- /charts/importer/templates/secret.yaml: -------------------------------------------------------------------------------- 1 | {{- if not .Values.fireflyiii.auth.existingSecret }} 2 | apiVersion: v1 3 | kind: Secret 4 | metadata: 5 | name: {{ include "importer.fullname" . }} 6 | labels: 7 | {{- include "importer.labels" . | nindent 4 }} 8 | data: 9 | accessToken: {{ .Values.fireflyiii.auth.accessToken | b64enc | quote }} 10 | {{- end }} 11 | -------------------------------------------------------------------------------- /charts/importer/templates/configmap.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.config.env }} 2 | apiVersion: v1 3 | kind: ConfigMap 4 | metadata: 5 | name: {{ include "importer.fullname" . }} 6 | labels: 7 | {{- include "importer.labels" . | nindent 4 }} 8 | data: 9 | {{- range $key, $value := .Values.config.env }} 10 | {{ $key }}: {{ $value | quote }} 11 | {{- end }} 12 | {{- end }} 13 | -------------------------------------------------------------------------------- /charts/importer/templates/secret-files.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.config.files }} 2 | apiVersion: v1 3 | kind: Secret 4 | metadata: 5 | name: {{ include "importer.fullname" . }}-files 6 | labels: 7 | {{- include "importer.labels" . | nindent 4 }} 8 | data: 9 | {{- range .Values.config.files }} 10 | {{ .name }}: {{ .content | b64enc }} 11 | {{- end }} 12 | {{- end }} 13 | -------------------------------------------------------------------------------- /kustomize/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - mysql.yaml 3 | - firefly-iii.yaml 4 | - ingress-firefly-iii-cron.yaml 5 | - firefly-iii-importer.yaml 6 | secretGenerator: 7 | - name: firefly-iii-secrets 8 | literals: 9 | - db_password=CHANGEMECHANGEME 10 | - app_key=CHANGEMECHANGEMECHANGEMECHANGEME 11 | - access_token=CHANGEMECHANGEMECHANGEME... 12 | - static_cron_token=CHANGE12CHAR 13 | -------------------------------------------------------------------------------- /.github/workflows/transfer.yml: -------------------------------------------------------------------------------- 1 | name: Issues - Transfer issues 2 | on: 3 | issues: 4 | types: 5 | - labeled 6 | jobs: 7 | transfer: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: Transfer 11 | uses: lando/transfer-issue-action@v2 12 | with: 13 | token: ${{ secrets.TRANSFER_ISSUE_TOKEN }} 14 | router: move:firefly-iii 15 | create_stub: false 16 | -------------------------------------------------------------------------------- /charts/firefly-iii/templates/secret.yaml: -------------------------------------------------------------------------------- 1 | {{ if and (.Values.secrets.env) (not .Values.config.existingSecret) }} 2 | apiVersion: v1 3 | kind: Secret 4 | metadata: 5 | name: {{ include "firefly-iii.fullname" . }} 6 | labels: 7 | {{- include "firefly-iii.labels" . | nindent 4 }} 8 | data: 9 | {{- range $key, $value := .Values.secrets.env }} 10 | {{ $key }}: {{ $value | b64enc | quote }} 11 | {{- end }} 12 | {{- end }} 13 | -------------------------------------------------------------------------------- /charts/importer/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: importer 3 | version: 1.5.1 4 | description: Deploys the importer chart for Firefly III 5 | type: application 6 | home: https://www.firefly-iii.org/ 7 | sources: 8 | - https://github.com/firefly-iii/data-importer 9 | maintainers: 10 | - name: morremeyer 11 | email: firefly-iii@mor.re 12 | icon: https://raw.githubusercontent.com/firefly-iii/firefly-iii/main/.github/assets/img/logo-small.png 13 | -------------------------------------------------------------------------------- /charts/importer/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "importer.fullname" . }} 5 | labels: 6 | {{- include "importer.labels" . | nindent 4 }} 7 | spec: 8 | type: {{ .Values.service.type }} 9 | ports: 10 | - port: {{ .Values.service.port }} 11 | targetPort: http 12 | protocol: TCP 13 | name: http 14 | selector: 15 | {{- include "importer.selectorLabels" . | nindent 4 }} 16 | -------------------------------------------------------------------------------- /charts/firefly-iii/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "firefly-iii.fullname" . }} 5 | labels: 6 | {{- include "firefly-iii.labels" . | nindent 4 }} 7 | spec: 8 | type: {{ .Values.service.type }} 9 | ports: 10 | - port: {{ .Values.service.port }} 11 | targetPort: http 12 | protocol: TCP 13 | name: http 14 | selector: 15 | {{- include "firefly-iii.selectorLabels" . | nindent 4 }} 16 | -------------------------------------------------------------------------------- /charts/importer/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /charts/firefly-iii/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /charts/firefly-iii-stack/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /charts/firefly-iii/templates/configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: {{ include "firefly-iii.fullname" . }} 5 | labels: 6 | {{- include "firefly-iii.labels" . | nindent 4 }} 7 | data: 8 | {{- range $key, $value := .Values.config.env }} 9 | {{- if ne $key "DB_HOST" }} 10 | {{ $key }}: {{ $value | quote }} 11 | {{- end }} 12 | {{- end }} 13 | DB_HOST: {{ (default (printf "%s-firefly-db" .Release.Name) .Values.config.env.DB_HOST) | quote }} 14 | -------------------------------------------------------------------------------- /helm/README.md: -------------------------------------------------------------------------------- 1 | # helm 2 | 3 | :information_source: This page serves to inform about the chart updates and will be removed with the 1.0.0 release of the **firefly-iii-stack** chart. 4 | 5 | The contents of this directory have been moved to [charts](../charts) to prepare for a 1.0.0 release of all components. 6 | 7 | If you're looking for the **firefly** chart that has been in this directory, check the [firefly-iii-stack chart](../charts/firefly-iii-stack/) which it has been renamed and reorganized to. 8 | -------------------------------------------------------------------------------- /.github/workflows/label.yml: -------------------------------------------------------------------------------- 1 | name: "Issues - Label issues to transfer" 2 | on: 3 | issues: 4 | types: [opened, edited] 5 | 6 | permissions: 7 | issues: write 8 | contents: read 9 | 10 | jobs: 11 | triage: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: github/issue-labeler@v3.4 #May not be the latest version 15 | with: 16 | configuration-path: .github/labeler.yml 17 | enable-versioned-regex: 0 18 | repo-token: ${{ secrets.TRANSFER_ISSUE_TOKEN }} 19 | -------------------------------------------------------------------------------- /charts/firefly-db/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *~ 18 | # Various IDEs 19 | .project 20 | .idea/ 21 | *.tmproj 22 | # my 2 cents 23 | *.tgz 24 | Makefile 25 | *.local.yaml -------------------------------------------------------------------------------- /charts/firefly-iii/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: firefly-iii 3 | description: Installs Firefly III 4 | home: https://www.firefly-iii.org/ 5 | icon: https://raw.githubusercontent.com/firefly-iii/firefly-iii/main/.github/assets/img/logo-small.png 6 | type: application 7 | version: 1.9.12 8 | # renovate: image=docker.io/fireflyiii/core 9 | appVersion: 6.4.9 10 | sources: 11 | - https://github.com/firefly-iii/firefly-iii/ 12 | maintainers: 13 | - name: morremeyer 14 | email: firefly-iii@mor.re 15 | -------------------------------------------------------------------------------- /charts/firefly-db/templates/firefly-db-svc.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | namespace: {{ .Release.Namespace }} 5 | name: {{ template "firefly-db.fullname" . }} 6 | labels: 7 | app: {{ template "firefly-db.name" . }} 8 | chart: {{ template "firefly-db.chart" . }} 9 | release: {{ .Release.Name }} 10 | heritage: {{ .Release.Service }} 11 | spec: 12 | selector: 13 | pod-label: {{ template "firefly-db.fullname" . }}-pod 14 | ports: 15 | - protocol: TCP 16 | port: 5432 -------------------------------------------------------------------------------- /kustomize/pv-firefly-iii.yaml.example: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolume 3 | metadata: 4 | name: data-firefly-iii 5 | spec: 6 | capacity: 7 | storage: 10Gi 8 | volumeMode: Filesystem 9 | accessModes: 10 | - ReadWriteOnce 11 | persistentVolumeReclaimPolicy: Delete 12 | storageClassName: local-storage 13 | local: 14 | path: /mnt/data/firefly-iii 15 | nodeAffinity: 16 | required: 17 | nodeSelectorTerms: 18 | - matchExpressions: 19 | - key: kubernetes.io/hostname 20 | operator: In 21 | values: 22 | - kube1 23 | -------------------------------------------------------------------------------- /kustomize/pv-firefly-iii-mysql.yaml.example: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolume 3 | metadata: 4 | name: data-firefly-iii-mysql 5 | spec: 6 | capacity: 7 | storage: 20Gi 8 | volumeMode: Filesystem 9 | accessModes: 10 | - ReadWriteOnce 11 | persistentVolumeReclaimPolicy: Delete 12 | storageClassName: local-storage 13 | local: 14 | path: /mnt/data/firefly-iii-mysql 15 | nodeAffinity: 16 | required: 17 | nodeSelectorTerms: 18 | - matchExpressions: 19 | - key: kubernetes.io/hostname 20 | operator: In 21 | values: 22 | - kube1 23 | -------------------------------------------------------------------------------- /.github/workflows/helm-docs.yml: -------------------------------------------------------------------------------- 1 | name: Helm Docs 2 | 3 | on: 4 | push: 5 | 6 | jobs: 7 | helm-docs: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v4 11 | - uses: actions/setup-go@v5 12 | with: 13 | # renovate: go-version 14 | go-version: 1.22 15 | 16 | - name: Install helm-docs 17 | run: go install github.com/norwoodj/helm-docs/cmd/helm-docs@latest 18 | 19 | - name: regenerate documentation 20 | run: $HOME/go/bin/helm-docs 21 | 22 | - name: Commit updated docs 23 | uses: EndBug/add-and-commit@v8 24 | with: 25 | message: 'docs: regenerate chart README.md' 26 | -------------------------------------------------------------------------------- /charts/firefly-db/templates/firefly-db-cm.yml: -------------------------------------------------------------------------------- 1 | {{- if not .Values.configs.existingSecret }} 2 | apiVersion: v1 3 | kind: ConfigMap 4 | metadata: 5 | namespace: {{ .Release.Namespace }} 6 | name: {{ template "firefly-db.fullname" . }}-config 7 | labels: 8 | app: {{ template "firefly-db.name" . }} 9 | chart: {{ template "firefly-db.chart" . }} 10 | release: {{ .Release.Name }} 11 | heritage: {{ .Release.Service }} 12 | data: 13 | {{- range $key, $value := .Values.configs }} 14 | {{- if ne $key "DBHOST" }} 15 | {{ $key }}: {{ $value | quote }} 16 | {{- end }} 17 | {{- end }} 18 | DBHOST: {{ (default (include "firefly-db.fullname" .) .Values.configs.DBHOST) | quote }} 19 | {{- end }} 20 | -------------------------------------------------------------------------------- /charts/firefly-db/templates/firefly-db-cron-backup.yml: -------------------------------------------------------------------------------- 1 | {{ if .Values.backupSchedule }} 2 | apiVersion: batch/v1 3 | kind: CronJob 4 | metadata: 5 | namespace: {{ .Release.Namespace }} 6 | name: {{ template "firefly-db.fullname" . }}-backup 7 | labels: 8 | app: {{ template "firefly-db.name" . }} 9 | chart: {{ template "firefly-db.chart" . }} 10 | release: {{ .Release.Name }} 11 | heritage: {{ .Release.Service }} 12 | spec: 13 | schedule: "{{ .Values.backupSchedule }}" 14 | successfulJobsHistoryLimit: 1 15 | failedJobsHistoryLimit: 1 16 | jobTemplate: 17 | spec: 18 | backoffLimit: 0 19 | template: 20 | {{- include "backupJobSpec" . | indent 8 }} 21 | {{ end }} 22 | -------------------------------------------------------------------------------- /charts/firefly-db/templates/firefly-db-pvc.yml: -------------------------------------------------------------------------------- 1 | {{- if eq .Values.storage.existingClaim "" }} 2 | apiVersion: v1 3 | kind: PersistentVolumeClaim 4 | metadata: 5 | namespace: {{ .Release.Namespace }} 6 | name: {{ printf "%s-%s" (include "firefly-db.fullname" .) "storage-claim" }} 7 | labels: 8 | app: {{ template "firefly-db.name" . }} 9 | chart: {{ template "firefly-db.chart" . }} 10 | release: {{ .Release.Name }} 11 | heritage: {{ .Release.Service }} 12 | spec: 13 | {{- with .Values.storage.class }} 14 | storageClassName: {{ . }} 15 | {{- end }} 16 | accessModes: 17 | - {{ .Values.storage.accessModes }} 18 | resources: 19 | requests: 20 | storage: {{ .Values.storage.dataSize }} 21 | {{- end }} 22 | -------------------------------------------------------------------------------- /kustomize/ingress-firefly-iii.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | # kubernetes.io/tls-acme: "true" 6 | # cert-manager.io/cluster-issuer: letsencrypt-prod 7 | nginx.ingress.kubernetes.io/proxy-buffer-size: "16k" 8 | labels: 9 | name: firefly-iii-ingress 10 | spec: 11 | rules: 12 | - host: firefly-iii.your-domain.org 13 | http: 14 | paths: 15 | - backend: 16 | service: 17 | name: firefly-iii 18 | port: 19 | number: 8080 20 | path: / 21 | pathType: Prefix 22 | # tls: 23 | # - hosts: 24 | # - firefly-iii.your-domain.org 25 | # secretName: firefly-iii.your-domain.org-tls 26 | 27 | -------------------------------------------------------------------------------- /.github/support.md: -------------------------------------------------------------------------------- 1 | # Welcome to Firefly III's k8n files on Github! 2 | 3 | :+1::tada: Thank you for taking the time to contribute something to Firefly III's k8n files! 4 | 5 | ## Bugs 6 | 7 | First of all: thank you for reporting a bug instead of ditching the tool altogether. If you find a bug, please take the time and see if the [demo site](https://demo.firefly-iii.org/) is also suffering from this bug. Include as many log files and details as you think are necessary. Bugs have a lot of priority! 8 | 9 | ## Installation problems 10 | 11 | Please take the time to read the [documentation](https://docs.firefly-iii.org/) and make sure you search through closed issues for the problems other people have had. Your problem may be among them! If not, open an issue and I will help where I can. -------------------------------------------------------------------------------- /charts/firefly-db/templates/firefly-backup-pvc.yml: -------------------------------------------------------------------------------- 1 | {{- if and (eq .Values.backup.destination "pvc") (eq .Values.backup.pvc.existingClaim "") }} 2 | apiVersion: v1 3 | kind: PersistentVolumeClaim 4 | metadata: 5 | namespace: {{ .Release.Namespace }} 6 | name: {{ printf "%s-%s" (include "firefly-db.fullname" .) "backup-storage-claim" }} 7 | labels: 8 | app: {{ template "firefly-db.name" . }} 9 | chart: {{ template "firefly-db.chart" . }} 10 | release: {{ .Release.Name }} 11 | heritage: {{ .Release.Service }} 12 | spec: 13 | {{- with .Values.backup.pvc.class }} 14 | storageClassName: {{ . }} 15 | {{- end }} 16 | accessModes: 17 | - {{ .Values.backup.pvc.accessModes }} 18 | resources: 19 | requests: 20 | storage: {{ .Values.backup.pvc.dataSize }} 21 | {{- end }} 22 | -------------------------------------------------------------------------------- /charts/firefly-iii-stack/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: firefly-iii-stack 3 | description: Installs Firefly III stack (db, app, importer) 4 | home: https://github.com/firefly-iii/kubernetes 5 | icon: https://raw.githubusercontent.com/firefly-iii/firefly-iii/main/.github/assets/img/logo-small.png 6 | type: application 7 | version: 0.9.1 8 | dependencies: 9 | - name: firefly-db 10 | version: 0.2.9 11 | condition: firefly-db.enabled 12 | repository: file://../firefly-db 13 | - name: firefly-iii 14 | version: 1.9.12 15 | condition: firefly-iii.enabled 16 | repository: file://../firefly-iii 17 | - name: importer 18 | version: 1.5.1 19 | condition: importer.enabled 20 | repository: file://../importer 21 | sources: 22 | - https://github.com/firefly-iii/kubernetes 23 | maintainers: 24 | - name: morremeyer 25 | email: firefly-iii@mor.re 26 | -------------------------------------------------------------------------------- /charts/firefly-db/README.md.gotmpl: -------------------------------------------------------------------------------- 1 | {{ template "chart.header" . }} 2 | {{ template "chart.deprecationWarning" . }} 3 | {{ template "chart.badgesSection" . }} 4 | 5 | {{ template "chart.description" . }} 6 | {{ template "chart.homepageLine" . }} 7 | {{ template "chart.maintainersSection" . }} 8 | {{ template "chart.sourcesSection" . }} 9 | {{ template "chart.requirementsSection" . }} 10 | 11 | ## Upgrading 12 | 13 | When a release introduces breaking changes, this section outlines the manual actions that need to be taken. 14 | 15 | ### From 0.0.2 to 0.0.3 16 | 17 | The storage class and access modes have been changed to match more setups without the need for configuration. If you want to keep the old settings, set the following values: 18 | 19 | ```yaml 20 | storage: 21 | class: nfs-client 22 | accessModes: ReadWriteMany 23 | ``` 24 | 25 | {{ template "chart.valuesSection" . }} 26 | -------------------------------------------------------------------------------- /charts/firefly-iii/templates/pvc.yaml: -------------------------------------------------------------------------------- 1 | {{- if and .Values.persistence.enabled (eq .Values.persistence.existingClaim "") }} 2 | apiVersion: v1 3 | kind: PersistentVolumeClaim 4 | metadata: 5 | name: {{ include "firefly-iii.fullname" . }} 6 | labels: 7 | {{- include "firefly-iii.labels" . | nindent 4 }} 8 | spec: 9 | accessModes: 10 | - {{ .Values.persistence.accessModes }} 11 | {{- if .Values.persistence.storageClassName }} 12 | storageClassName: {{ .Values.persistence.storageClassName }} 13 | {{- end }} 14 | resources: 15 | requests: 16 | storage: {{ .Values.persistence.storage }} 17 | {{- if .Values.persistence.selector }} 18 | selector: 19 | {{- toYaml .Values.persistence.selector | nindent 4 }} 20 | {{- end }} 21 | {{- if .Values.persistence.volumeName }} 22 | volumeName: {{ .Values.persistence.volumeName | quote }} 23 | {{- end }} 24 | {{- end }} -------------------------------------------------------------------------------- /charts/firefly-db/templates/firefly-db-backup-job.yml: -------------------------------------------------------------------------------- 1 | {{- if and (eq .Values.backup.destination "http") (empty .Values.configs.BACKUP_URL) }} 2 | {{- fail "BACKUP_URL must be set when backup.destination is 'http'" }} 3 | {{- end }} 4 | 5 | apiVersion: batch/v1 6 | kind: Job 7 | metadata: 8 | namespace: {{ .Release.Namespace }} 9 | name: {{ template "firefly-db.fullname" . }}-backup-job 10 | labels: 11 | app: {{ template "firefly-db.name" . }} 12 | chart: {{ template "firefly-db.chart" . }} 13 | release: {{ .Release.Name }} 14 | heritage: {{ .Release.Service }} 15 | annotations: 16 | "helm.sh/hook": pre-delete,pre-upgrade 17 | "helm.sh/hook-weight": "-5" 18 | "helm.sh/hook-delete-policy": hook-succeeded 19 | spec: 20 | backoffLimit: 0 21 | ttlSecondsAfterFinished: 100 22 | parallelism: 1 23 | completions: 1 24 | template: 25 | {{- include "backupJobSpec" . | indent 4 }} 26 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | 15 | 16 | This PR fixes issue # (if relevant). 17 | 18 | Changes in this pull request: 19 | 20 | - 21 | - 22 | - 23 | -------------------------------------------------------------------------------- /kustomize/ingress-firefly-iii-importer.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | # kubernetes.io/tls-acme: "true" 6 | # cert-manager.io/cluster-issuer: letsencrypt-prod 7 | # # Use these annotation if you're using nginx ingress 8 | # nginx.ingress.kubernetes.io/proxy-body-size: "0" 9 | # nginx.ingress.kubernetes.io/proxy-buffer-size: "8k" 10 | nginx.org/client-max-body-size: "0" 11 | nginx.org/proxy-buffer-size: "8k" 12 | labels: 13 | name: firefly-iii-importer-ingress 14 | spec: 15 | rules: 16 | - host: importer-firefly-iii.your-domain.org 17 | http: 18 | paths: 19 | - backend: 20 | service: 21 | name: firefly-iii-importer 22 | port: 23 | number: 8080 24 | path: / 25 | pathType: Prefix 26 | # tls: 27 | # - hosts: 28 | # - importer-firefly-iii.your-domain.org 29 | # secretName: importer-firefly-iii.your-domain.org-tls 30 | 31 | -------------------------------------------------------------------------------- /kustomize/ingress-firefly-iii-cron.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: batch/v1 2 | kind: CronJob 3 | metadata: 4 | name: "firefly-iii-cron" 5 | spec: 6 | schedule: "*/15 * * * *" 7 | concurrencyPolicy: Forbid 8 | failedJobsHistoryLimit: 2 9 | successfulJobsHistoryLimit: 2 10 | jobTemplate: 11 | spec: 12 | activeDeadlineSeconds: 120 13 | backoffLimit: 5 14 | template: 15 | metadata: 16 | labels: 17 | app: firefly-iii 18 | tier: cron 19 | spec: 20 | containers: 21 | - name: cron 22 | image: busybox 23 | imagePullPolicy: IfNotPresent 24 | command: 25 | - wget 26 | args: 27 | - "firefly-iii:8080/api/v1/cron/$(STATIC_CRON_TOKEN)" 28 | env: 29 | - name: STATIC_CRON_TOKEN 30 | valueFrom: 31 | secretKeyRef: 32 | name: firefly-iii-secrets 33 | key: static_cron_token 34 | restartPolicy: Never 35 | -------------------------------------------------------------------------------- /charts/firefly-iii-stack/values.yaml: -------------------------------------------------------------------------------- 1 | firefly-db: 2 | # if you set this to false it will not be installed 3 | enabled: true 4 | image: 5 | repository: postgres 6 | tag: 10-alpine 7 | pullPolicy: IfNotPresent 8 | 9 | storage: 10 | class: ~ 11 | accessModes: ~ # Change as needed for your storageClass https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes 12 | dataSize: 1Gi 13 | 14 | # environment variables 15 | configs: 16 | RESTORE_URL: "" 17 | BACKUP_URL: "" 18 | PGPASSWORD: "" 19 | DBHOST: "" # Default is the name of the postgres service 20 | DBPORT: "5432" 21 | DBNAME: firefly 22 | DBUSER: firefly 23 | TZ: Europe/Berlin 24 | 25 | backupSchedule: "0 3 * * *" 26 | 27 | firefly-iii: 28 | # -- Set to false to not deploy Firefly III 29 | enabled: true 30 | config: 31 | env: 32 | DB_HOST: "" 33 | DEFAULT_LANGUAGE: "en_US" 34 | DEFAULT_LOCALE: "equal" 35 | TZ: "Europe/Amsterdam" 36 | TRUSTED_PROXIES: "**" 37 | 38 | importer: 39 | # -- Set to false to not deploy the importer 40 | enabled: true 41 | -------------------------------------------------------------------------------- /charts/firefly-iii/templates/hpa.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.autoscaling.enabled }} 2 | apiVersion: autoscaling/v2 3 | kind: HorizontalPodAutoscaler 4 | metadata: 5 | name: {{ include "firefly-iii.fullname" . }} 6 | labels: 7 | {{- include "firefly-iii.labels" . | nindent 4 }} 8 | spec: 9 | scaleTargetRef: 10 | apiVersion: apps/v1 11 | kind: Deployment 12 | name: {{ include "firefly-iii.fullname" . }} 13 | minReplicas: {{ .Values.autoscaling.minReplicas }} 14 | maxReplicas: {{ .Values.autoscaling.maxReplicas }} 15 | metrics: 16 | {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} 17 | - type: Resource 18 | resource: 19 | name: cpu 20 | target: 21 | type: Utilization 22 | averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} 23 | {{- end }} 24 | {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} 25 | - type: Resource 26 | resource: 27 | name: memory 28 | target: 29 | type: Utilization 30 | averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} 31 | {{- end }} 32 | {{- end }} 33 | -------------------------------------------------------------------------------- /charts/firefly-db/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* vim: set filetype=mustache: */}} 2 | {{/* 3 | Expand the name of the chart. 4 | */}} 5 | {{- define "firefly-db.name" -}} 6 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} 7 | {{- end -}} 8 | 9 | {{/* 10 | Create a default fully qualified app name. 11 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 12 | If release name contains chart name it will be used as a full name. 13 | */}} 14 | {{- define "firefly-db.fullname" -}} 15 | {{- if .Values.fullnameOverride -}} 16 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} 17 | {{- else -}} 18 | {{- $name := default .Chart.Name .Values.nameOverride -}} 19 | {{- if contains $name .Release.Name -}} 20 | {{- .Release.Name | trunc 63 | trimSuffix "-" -}} 21 | {{- else -}} 22 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} 23 | {{- end -}} 24 | {{- end -}} 25 | {{- end -}} 26 | 27 | {{/* 28 | Create chart name and version as used by the chart label. 29 | */}} 30 | {{- define "firefly-db.chart" -}} 31 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} 32 | {{- end -}} -------------------------------------------------------------------------------- /charts/firefly-db/values.yaml: -------------------------------------------------------------------------------- 1 | image: 2 | repository: postgres 3 | tag: 10-alpine 4 | pullPolicy: IfNotPresent 5 | 6 | storage: 7 | class: ~ 8 | accessModes: ReadWriteOnce 9 | dataSize: 1Gi 10 | # -- Use an existing PersistentVolumeClaim, overrides values above 11 | existingClaim: "" 12 | 13 | backup: 14 | # There are two possible backup destinations currently implemented, http and pvc 15 | destination: pvc 16 | pvc: 17 | class: ~ 18 | accessModes: ReadWriteOnce 19 | dataSize: 1Gi 20 | # -- Use an existing PersistentVolumeClaim, overrides values above 21 | existingClaim: "" 22 | 23 | configs: 24 | RESTORE_URL: "" 25 | BACKUP_URL: "" # -- Must have value if backup.destination is set to http 26 | PGPASSWORD: "" 27 | DBHOST: "" # -- Default is the name of the postgres service 28 | DBPORT: "5432" 29 | DBNAME: firefly 30 | DBUSER: firefly 31 | TZ: Europe/Amsterdam 32 | POSTGRES_HOST_AUTH_METHOD: trust 33 | POSTGRES_USER: firefly 34 | POSTGRES_PASSWORD: "" 35 | # -- Set this to the name of a secret to load environment variables from. If defined, values in the secret will override values in configs 36 | existingSecret: "" 37 | 38 | backupSchedule: "0 3 * * *" 39 | 40 | nodeSelector: {} 41 | -------------------------------------------------------------------------------- /charts/importer/README.md.gotmpl: -------------------------------------------------------------------------------- 1 | {{ template "chart.header" . }} 2 | {{ template "chart.deprecationWarning" . }} 3 | {{ template "chart.badgesSection" . }} 4 | 5 | {{ template "chart.description" . }} 6 | {{ template "chart.homepageLine" . }} 7 | {{ template "chart.maintainersSection" . }} 8 | {{ template "chart.sourcesSection" . }} 9 | {{ template "chart.requirementsSection" . }} 10 | 11 | ## Setup 12 | 13 | :warning: When enabling the ingress, be aware that the importer does not have any authentication. You are responsible to configure authentication at the ingress level 14 | 15 | There are some values that you should check before installing this chart: 16 | 17 | * `trustedProxies` (default: `"**"`): The proxies that are trusted by the importer 18 | * `fireflyiii.url` (default: `"http://firefly-firefly-iii:8080"`): The URL at which Firefly III is available 19 | 20 | For authentication, use `fireflyiii.auth.existingSecret` if you have an existing Secret with `data.accessToken` specified. 21 | When you set `fireflyiii.auth.accessToken`, be aware that this is a secret and should not be commited to a repository. 22 | 23 | ## Upgrading 24 | 25 | When a release introduces breaking changes, this section outlines the manual actions that need to be taken. 26 | 27 | {{ template "chart.valuesSection" . }} 28 | -------------------------------------------------------------------------------- /kustomize/firefly-iii-importer.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: firefly-iii-importer 5 | labels: 6 | app: firefly-iii-importer 7 | spec: 8 | clusterIP: None 9 | ports: 10 | - port: 8080 11 | selector: 12 | app: firefly-iii-importer 13 | tier: frontend 14 | 15 | --- 16 | 17 | apiVersion: apps/v1 18 | kind: Deployment 19 | metadata: 20 | name: firefly-iii-importer 21 | labels: 22 | app: firefly-iii-importer 23 | spec: 24 | selector: 25 | matchLabels: 26 | app: firefly-iii-importer 27 | tier: frontend 28 | strategy: 29 | type: Recreate 30 | template: 31 | metadata: 32 | labels: 33 | app: firefly-iii-importer 34 | tier: frontend 35 | spec: 36 | containers: 37 | - image: fireflyiii/data-importer:version-1.9.1 38 | name: firefly-iii-importer 39 | env: 40 | - name: FIREFLY_III_ACCESS_TOKEN 41 | valueFrom: 42 | secretKeyRef: 43 | name: firefly-iii-secrets 44 | key: access_token 45 | - name: FIREFLY_III_URL 46 | value: "http://firefly-iii:8080" 47 | - name: TRUSTED_PROXIES 48 | value: "**" 49 | ports: 50 | - containerPort: 8080 51 | name: firefly-iii 52 | imagePullPolicy: Always 53 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/fr.yml: -------------------------------------------------------------------------------- 1 | name: Feature request 2 | description: Request a feature or enhancement in the Firefly III kubernetes code 3 | body: 4 | - type: checkboxes 5 | attributes: 6 | label: Support guidelines 7 | description: Please read the support guidelines before proceeding. 8 | options: 9 | - label: I've read the [support guidelines](https://github.com/firefly-iii/firefly-iii/blob/main/.github/support.md) 10 | required: true 11 | - label: My request is not listed as [a very good idea, but unfortunately...](https://docs.firefly-iii.org/explanation/more-information/what-its-not/) 12 | required: true 13 | - label: I've used [the search](https://github.com/firefly-iii/firefly-iii/issues?q=is%3Aissue) and this has not been requested before. 14 | required: true 15 | 16 | - type: textarea 17 | attributes: 18 | label: Description 19 | description: Please describe your feature request 20 | placeholder: | 21 | - I would like Firefly III to do (thing). 22 | - What if you would add feature (feature here)? 23 | - Firefly III doesn't do (thing). 24 | validations: 25 | required: true 26 | 27 | - type: textarea 28 | attributes: 29 | label: Additional context 30 | description: Add any other context or screenshots about the feature request here. 31 | -------------------------------------------------------------------------------- /.devcontainer/library-scripts/govc-completion.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # govc Bash completion script 4 | # place in etc/bash_completion.d/ or source on command line with "." 5 | 6 | _govc_complete() 7 | { 8 | local cur prev subcmd 9 | prev=${COMP_WORDS[COMP_CWORD-1]} 10 | cur=${COMP_WORDS[COMP_CWORD]} 11 | subcmd=${COMP_WORDS[1]} 12 | COMPREPLY=() 13 | 14 | if [[ ${prev} == "govc" ]] ; then # show subcommands, no options 15 | COMPREPLY=( $(compgen -W "$(govc -h | grep -v Usage | tr -s '\n' ' ')" -- ${cur}) ) 16 | return 0 17 | 18 | elif [[ ${cur} == "-"* ]] ; then 19 | : # drop out and show options 20 | 21 | elif [[ ${subcmd} == "ls" ]] ; then # not completing an option, try for appropriate values 22 | if [[ ${prev} == "-t" ]] ; then 23 | COMPREPLY=( $(compgen -W "$(govc ls -l "/**" | awk '{print $2}' | \ 24 | sort -u | tr -d '()' | tr '\n' ' ' )" -- ${cur}) ) 25 | else 26 | COMPREPLY=( $(compgen -W "$(govc ls "${cur:-/*}*" | tr -s '\n' ' ' )" -- ${cur}) ) 27 | fi 28 | 29 | elif [[ ${subcmd} == "vm."* || ${prev} == "-vm" ]] ; then 30 | COMPREPLY=( $(compgen -W "$(govc ls -t VirtualMachine -l "${cur}*" | \ 31 | awk '{print $1}' | tr -s '\n' ' ' )" -- ${cur}) ) 32 | fi 33 | 34 | # did not hit any specifcs so show all options from help 35 | if [[ -z ${COMPREPLY} ]]; then 36 | COMPREPLY=( $(compgen -W "-h $(govc ${subcmd} -h | awk '{print $1}' | \ 37 | grep "^-" | sed -e 's/=.*//g' | tr -s '\n' ' ' )" -- ${cur}) ) 38 | fi 39 | 40 | return 0 41 | } 42 | complete -F _govc_complete govc 43 | -------------------------------------------------------------------------------- /kustomize/mysql.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: firefly-iii-mysql 5 | labels: 6 | app: firefly-iii 7 | spec: 8 | ports: 9 | - port: 3306 10 | selector: 11 | app: firefly-iii 12 | tier: mysql 13 | clusterIP: None 14 | --- 15 | apiVersion: v1 16 | kind: PersistentVolumeClaim 17 | metadata: 18 | name: mysql-pv-claim 19 | labels: 20 | app: firefly-iii 21 | spec: 22 | accessModes: 23 | - ReadWriteOnce 24 | resources: 25 | requests: 26 | storage: 20Gi 27 | --- 28 | apiVersion: apps/v1 29 | kind: Deployment 30 | metadata: 31 | name: firefly-iii-mysql 32 | labels: 33 | app: firefly-iii 34 | spec: 35 | selector: 36 | matchLabels: 37 | app: firefly-iii 38 | tier: mysql 39 | strategy: 40 | type: Recreate 41 | template: 42 | metadata: 43 | labels: 44 | app: firefly-iii 45 | tier: mysql 46 | spec: 47 | containers: 48 | - image: yobasystems/alpine-mariadb:latest 49 | name: mysql 50 | env: 51 | - name: MYSQL_ROOT_PASSWORD 52 | valueFrom: 53 | secretKeyRef: 54 | name: firefly-iii-secrets 55 | key: db_password 56 | ports: 57 | - containerPort: 3306 58 | name: mysql 59 | volumeMounts: 60 | - name: mysql-persistent-storage 61 | mountPath: /var/lib/mysql 62 | volumes: 63 | - name: mysql-persistent-storage 64 | persistentVolumeClaim: 65 | claimName: mysql-pv-claim 66 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "k8s devcontainer", 3 | "dockerFile": "Dockerfile", 4 | "remoteEnv": { 5 | "SYNC_LOCALHOST_KUBECONFIG": "true", 6 | "ANSIBLE_CONFIG": "./ansible.cfg", 7 | }, 8 | 9 | "mounts": [ 10 | // bind local docker socket to container 11 | "source=/var/run/docker.sock,target=/var/run/docker-host.sock,type=bind", 12 | // sync local kube config 13 | "source=${env:HOME}${env:USERPROFILE}/.kube,target=/usr/local/share/kube-localhost,type=bind", 14 | // sync certs in your .minikube folder 15 | // "source=${env:HOME}${env:USERPROFILE}/.minikube,target=/usr/local/share/minikube-localhost,type=bind", 16 | ], 17 | 18 | // Set *default* container specific settings.json values on container create. 19 | "settings": { 20 | "terminal.integrated.shell.linux": "/usr/bin/zsh" 21 | }, 22 | 23 | // Add the IDs of extensions you want installed when the container is created. 24 | "extensions": [ 25 | "hashicorp.terraform", 26 | "ms-azuretools.vscode-docker", 27 | "ms-kubernetes-tools.vscode-kubernetes-tools", 28 | "ms-vscode.powershell", 29 | "redhat.vscode-yaml", 30 | "redhat.vscode-xml", 31 | ], 32 | 33 | // Use 'forwardPorts' to make a list of ports inside the container available locally. 34 | // "forwardPorts": [], 35 | 36 | // "postCreateCommand": "", 37 | 38 | // required for vault to run 39 | "runArgs": [ "--cap-add=IPC_LOCK" ], 40 | 41 | // Uncomment to connect as a non-root user. See https://aka.ms/vscode-remote/containers/non-root. 42 | "overrideCommand": false, 43 | "remoteUser": "vscode" 44 | } -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug.yml: -------------------------------------------------------------------------------- 1 | name: Bug report 2 | description: Report a bug in the Firefly III Kubernetes code 3 | body: 4 | - type: checkboxes 5 | attributes: 6 | label: Support guidelines 7 | description: Please read the support guidelines before proceeding. 8 | options: 9 | - label: I've read the [support guidelines](https://github.com/firefly-iii/firefly-iii/blob/main/.github/support.md) 10 | required: true 11 | 12 | - type: checkboxes 13 | attributes: 14 | label: I've found a bug and checked that ... 15 | description: Make sure that your request fulfills all of the following requirements. If one requirement cannot be satisfied, please explain why. 16 | options: 17 | - label: ... [the documentation](https://docs.firefly-iii.org/) does not mention anything about my problem 18 | - label: ... there are no open or closed issues that are related to my problem 19 | - label: ... it's [definitely a Firefly III issue, not me](https://github.com/firefly-iii/firefly-iii/blob/main/.github/its_you_not_me.md) 20 | 21 | - type: textarea 22 | attributes: 23 | label: Description 24 | description: Please provide a brief description of the bug in 1-2 sentences. 25 | validations: 26 | required: true 27 | 28 | - type: textarea 29 | attributes: 30 | label: Debug information 31 | description: Please provide the table from the /debug page. Do not add backticks or quotes. 32 | placeholder: The output from the /debug page 33 | validations: 34 | required: true 35 | 36 | - type: textarea 37 | attributes: 38 | label: Additional info 39 | description: Please provide any additional information that seems useful. 40 | -------------------------------------------------------------------------------- /charts/firefly-db/templates/backup.tpl: -------------------------------------------------------------------------------- 1 | {{ define "backupJobSpec" }} 2 | spec: 3 | containers: 4 | - name: {{ template "firefly-db.fullname" . }}-backup-job 5 | image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" 6 | imagePullPolicy: IfNotPresent 7 | envFrom: 8 | {{- if not .Values.configs.existingSecret }} 9 | - configMapRef: 10 | name: {{ template "firefly-db.fullname" . }}-config 11 | {{- else }} 12 | - secretRef: 13 | name: {{ .Values.configs.existingSecret }} 14 | {{- end }} 15 | command: 16 | - /bin/sh 17 | - -c 18 | - | 19 | set -e 20 | echo "creating backup file" 21 | pg_dump -h $DBHOST -p $DBPORT -U $DBUSER --format=p --clean -d $DBNAME > /var/lib/backup/$DBNAME.sql 22 | ls -la 23 | {{- if eq .Values.backup.destination "http" }} 24 | if [ -z "$BACKUP_URL" ]; then 25 | echo "ERROR: BACKUP_URL is required when backup.destination is set to 'http'. Backup will not be uploaded, but remain in PVC." 26 | else 27 | apk update 28 | apk add curl 29 | echo "uploading backup file" 30 | curl -F "filename=@/var/lib/backup/${DBNAME}.sql" $BACKUP_URL || { 31 | echo "HTTP upload failed. Backup remains in PVC." 32 | } 33 | fi 34 | {{- end }} 35 | echo "done" 36 | volumeMounts: 37 | - name: backup-storage 38 | mountPath: /var/lib/backup 39 | restartPolicy: Never 40 | volumes: 41 | - name: backup-storage 42 | {{- if eq .Values.backup.destination "pvc" }} 43 | persistentVolumeClaim: 44 | claimName: {{ default (printf "%s-%s" (include "firefly-db.fullname" .) "backup-storage-claim") .Values.backup.pvc.existingClaim }} 45 | {{- else }} 46 | emptyDir: {} 47 | {{- end }} 48 | {{ end }} 49 | -------------------------------------------------------------------------------- /.devcontainer/README.md: -------------------------------------------------------------------------------- 1 | # Infrastructure as Code Dev-Container 2 | 3 | 4 | The Dockerfile is based on this [Dockerfile](https://github.com/microsoft/vscode-dev-containers/blob/master/containers/kubernetes-helm/.devcontainer/Dockerfile) and contains the following modifications: 5 | - switched base image to python dev-container (for ansible) 6 | - removed `common-debian.sh` because the base image already contains this script 7 | - moved `copy-kube-config.sh` to `library-scripts`-folder and updated reference in Dockerfile 8 | - the end of the base Dockerfile is marked with a comment 9 | - added missing ENTRYPOINT/CMD entry for docker-in-docker usage (taken from this [Dockerfile](https://github.com/microsoft/vscode-dev-containers/blob/master/containers/docker-from-docker/.devcontainer/Dockerfile)) 10 | 11 | The Dockerfile contains the following additions: 12 | - install latest Node.js LTS-version 13 | - install additional tools: 14 | - ansible (latest) 15 | - govc (0.24.0) 16 | - packer (latest) 17 | - powershell (latest) 18 | - terraform (latest) 19 | - vault (latest) 20 | - configure bash/zsh auto completion for: 21 | - ansible 22 | - docker 23 | - govc 24 | - helm 25 | - kubectl 26 | - packer 27 | - terraform 28 | - vault 29 | 30 | 31 | ## Library Scripts from GitHub 32 | 33 | The library scripts are copied from GitHub and do not contain any modifications. 34 | 35 | 1. `copy-kube-config.sh` (version: 2020-07-27) 36 | https://github.com/microsoft/vscode-dev-containers/blob/master/containers/kubernetes-helm/.devcontainer/copy-kube-config.sh 37 | 2. `docker-debian.sh` (version: 2021-03-09) 38 | https://github.com/microsoft/vscode-dev-containers/blob/master/script-library/docker-debian.sh 39 | 3. `govc-completion.sh` (version: 2017-03-17) 40 | https://github.com/vmware/govmomi/blob/master/scripts/govc_bash_completion 41 | -------------------------------------------------------------------------------- /charts/firefly-db/templates/firefly-db-deploy.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | namespace: {{ .Release.Namespace }} 5 | name: {{ template "firefly-db.fullname" . }}-postgre-db 6 | labels: 7 | app: {{ template "firefly-db.name" . }} 8 | chart: {{ template "firefly-db.chart" . }} 9 | release: {{ .Release.Name }} 10 | heritage: {{ .Release.Service }} 11 | spec: 12 | replicas: 1 13 | selector: 14 | matchLabels: 15 | pod-label: {{ template "firefly-db.fullname" . }}-pod 16 | template: 17 | metadata: 18 | labels: 19 | pod-label: {{ template "firefly-db.fullname" . }}-pod 20 | spec: 21 | containers: 22 | - name: {{ template "firefly-db.fullname" . }} 23 | image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" 24 | imagePullPolicy: {{ .Values.image.pullPolicy }} 25 | envFrom: 26 | {{- if not .Values.configs.existingSecret }} 27 | - configMapRef: 28 | name: {{ template "firefly-db.fullname" . }}-config 29 | {{- else }} 30 | - secretRef: 31 | name: {{ .Values.configs.existingSecret }} 32 | {{- end }} 33 | resources: 34 | requests: 35 | memory: "128Mi" 36 | cpu: "250m" 37 | limits: 38 | memory: "512Mi" 39 | cpu: "500m" 40 | volumeMounts: 41 | - name: db-storage 42 | mountPath: /var/lib/postgresql/data 43 | subPath: data 44 | volumes: 45 | - name: db-storage 46 | persistentVolumeClaim: 47 | claimName: {{ default (printf "%s-%s" (include "firefly-db.fullname" .) "storage-claim") .Values.storage.existingClaim }} 48 | {{- with .Values.nodeSelector }} 49 | nodeSelector: 50 | {{- toYaml . | nindent 8 }} 51 | {{- end }} 52 | -------------------------------------------------------------------------------- /charts/importer/templates/ingress.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.ingress.enabled -}} 2 | {{- $fullName := include "importer.fullname" . -}} 3 | {{- $svcPort := .Values.service.port -}} 4 | {{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} 5 | {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} 6 | {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} 7 | {{- end }} 8 | {{- end }} 9 | {{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} 10 | apiVersion: networking.k8s.io/v1 11 | {{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} 12 | apiVersion: networking.k8s.io/v1beta1 13 | {{- else -}} 14 | apiVersion: extensions/v1beta1 15 | {{- end }} 16 | kind: Ingress 17 | metadata: 18 | name: {{ $fullName }} 19 | labels: 20 | {{- include "importer.labels" . | nindent 4 }} 21 | {{- with .Values.ingress.annotations }} 22 | annotations: 23 | {{- toYaml . | nindent 4 }} 24 | {{- end }} 25 | spec: 26 | {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} 27 | ingressClassName: {{ .Values.ingress.className }} 28 | {{- end }} 29 | {{- if .Values.ingress.tls }} 30 | tls: 31 | {{- range .Values.ingress.tls }} 32 | - hosts: 33 | {{- range .hosts }} 34 | - {{ . | quote }} 35 | {{- end }} 36 | secretName: {{ .secretName }} 37 | {{- end }} 38 | {{- end }} 39 | rules: 40 | {{- range .Values.ingress.hosts }} 41 | - host: {{ . | quote }} 42 | http: 43 | paths: 44 | - path: / 45 | pathType: Prefix 46 | backend: 47 | service: 48 | name: {{ $fullName }} 49 | port: 50 | number: {{ $svcPort }} 51 | {{- end }} 52 | {{- end }} 53 | -------------------------------------------------------------------------------- /charts/firefly-iii/templates/ingress.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.ingress.enabled -}} 2 | {{- $fullName := include "firefly-iii.fullname" . -}} 3 | {{- $svcPort := .Values.service.port -}} 4 | {{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} 5 | {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} 6 | {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} 7 | {{- end }} 8 | {{- end }} 9 | {{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} 10 | apiVersion: networking.k8s.io/v1 11 | {{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} 12 | apiVersion: networking.k8s.io/v1beta1 13 | {{- else -}} 14 | apiVersion: extensions/v1beta1 15 | {{- end }} 16 | kind: Ingress 17 | metadata: 18 | name: {{ $fullName }} 19 | labels: 20 | {{- include "firefly-iii.labels" . | nindent 4 }} 21 | {{- with .Values.ingress.annotations }} 22 | annotations: 23 | {{- toYaml . | nindent 4 }} 24 | {{- end }} 25 | spec: 26 | {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} 27 | ingressClassName: {{ .Values.ingress.className }} 28 | {{- end }} 29 | {{- if .Values.ingress.tls }} 30 | tls: 31 | {{- range .Values.ingress.tls }} 32 | - hosts: 33 | {{- range .hosts }} 34 | - {{ . | quote }} 35 | {{- end }} 36 | secretName: {{ .secretName }} 37 | {{- end }} 38 | {{- end }} 39 | rules: 40 | {{- range .Values.ingress.hosts }} 41 | - host: {{ . | quote }} 42 | http: 43 | paths: 44 | - path: / 45 | pathType: Prefix 46 | backend: 47 | service: 48 | name: {{ $fullName }} 49 | port: 50 | number: {{ $svcPort }} 51 | {{- end }} 52 | {{- end }} 53 | -------------------------------------------------------------------------------- /.devcontainer/library-scripts/copy-kube-config.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -i 2 | 3 | # Copies localhost's ~/.kube/config file into the container and swap out localhost 4 | # for host.docker.internal whenever a new shell starts to keep them in sync. 5 | if [ "$SYNC_LOCALHOST_KUBECONFIG" = "true" ] && [ -d "/usr/local/share/kube-localhost" ]; then 6 | mkdir -p $HOME/.kube 7 | sudo cp -r /usr/local/share/kube-localhost/* $HOME/.kube 8 | sudo chown -R $(id -u) $HOME/.kube 9 | sed -i -e "s/localhost/host.docker.internal/g" $HOME/.kube/config 10 | sed -i -e "s/127.0.0.1/host.docker.internal/g" $HOME/.kube/config 11 | 12 | # If .minikube was mounted, set up client cert/key 13 | if [ -d "/usr/local/share/minikube-localhost" ]; then 14 | mkdir -p $HOME/.minikube 15 | sudo cp -r /usr/local/share/minikube-localhost/ca.crt $HOME/.minikube 16 | # Location varies between versions of minikube 17 | if [ -f "/usr/local/share/minikube-localhost/client.crt" ]; then 18 | sudo cp -r /usr/local/share/minikube-localhost/client.crt $HOME/.minikube 19 | sudo cp -r /usr/local/share/minikube-localhost/client.key $HOME/.minikube 20 | elif [ -f "/usr/local/share/minikube-localhost/profiles/minikube/client.crt" ]; then 21 | sudo cp -r /usr/local/share/minikube-localhost/profiles/minikube/client.crt $HOME/.minikube 22 | sudo cp -r /usr/local/share/minikube-localhost/profiles/minikube/client.key $HOME/.minikube 23 | fi 24 | sudo chown -R $(id -u) $HOME/.minikube 25 | 26 | # Point .kube/config to the correct locaiton of the certs 27 | sed -i -r "s|(\s*certificate-authority:\s).*|\\1$HOME\/.minikube\/ca.crt|g" $HOME/.kube/config 28 | sed -i -r "s|(\s*client-certificate:\s).*|\\1$HOME\/.minikube\/client.crt|g" $HOME/.kube/config 29 | sed -i -r "s|(\s*client-key:\s).*|\\1$HOME\/.minikube\/client.key|g" $HOME/.kube/config 30 | fi 31 | fi 32 | -------------------------------------------------------------------------------- /charts/importer/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* 2 | Expand the name of the chart. 3 | */}} 4 | {{- define "importer.name" -}} 5 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} 6 | {{- end }} 7 | 8 | {{/* 9 | Create a default fully qualified app name. 10 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 11 | If release name contains chart name it will be used as a full name. 12 | */}} 13 | {{- define "importer.fullname" -}} 14 | {{- if .Values.fullnameOverride }} 15 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} 16 | {{- else }} 17 | {{- $name := default .Chart.Name .Values.nameOverride }} 18 | {{- if contains $name .Release.Name }} 19 | {{- .Release.Name | trunc 63 | trimSuffix "-" }} 20 | {{- else }} 21 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} 22 | {{- end }} 23 | {{- end }} 24 | {{- end }} 25 | 26 | {{/* 27 | Create chart name and version as used by the chart label. 28 | */}} 29 | {{- define "importer.chart" -}} 30 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} 31 | {{- end }} 32 | 33 | {{/* 34 | Common labels 35 | */}} 36 | {{- define "importer.labels" -}} 37 | helm.sh/chart: {{ include "importer.chart" . }} 38 | {{ include "importer.selectorLabels" . }} 39 | {{- if .Chart.AppVersion }} 40 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 41 | {{- end }} 42 | app.kubernetes.io/managed-by: {{ .Release.Service }} 43 | {{- end }} 44 | 45 | {{/* 46 | Selector labels 47 | */}} 48 | {{- define "importer.selectorLabels" -}} 49 | app.kubernetes.io/name: {{ include "importer.name" . }} 50 | app.kubernetes.io/instance: {{ .Release.Name }} 51 | {{- end }} 52 | 53 | {{/* 54 | Create the name of the service account to use 55 | */}} 56 | {{- define "importer.serviceAccountName" -}} 57 | {{- if .Values.serviceAccount.create }} 58 | {{- default (include "importer.fullname" .) .Values.serviceAccount.name }} 59 | {{- else }} 60 | {{- default "default" .Values.serviceAccount.name }} 61 | {{- end }} 62 | {{- end }} 63 | -------------------------------------------------------------------------------- /charts/firefly-db/templates/firefly-db-restore-job.yml: -------------------------------------------------------------------------------- 1 | apiVersion: batch/v1 2 | kind: Job 3 | metadata: 4 | namespace: {{ .Release.Namespace }} 5 | name: {{ template "firefly-db.fullname" . }}-restore 6 | labels: 7 | app: {{ template "firefly-db.name" . }} 8 | chart: {{ template "firefly-db.chart" . }} 9 | release: {{ .Release.Name }} 10 | heritage: {{ .Release.Service }} 11 | annotations: 12 | "helm.sh/hook": post-install 13 | "helm.sh/hook-weight": "-5" 14 | "helm.sh/hook-delete-policy": hook-succeeded 15 | spec: 16 | ttlSecondsAfterFinished: 100 17 | parallelism: 1 18 | completions: 1 19 | template: 20 | spec: 21 | containers: 22 | - name: {{ template "firefly-db.fullname" . }}-restore 23 | image: alpine:3.13 24 | imagePullPolicy: IfNotPresent 25 | envFrom: 26 | {{- if not .Values.configs.existingSecret }} 27 | - configMapRef: 28 | name: {{ template "firefly-db.fullname" . }}-config 29 | {{- else }} 30 | - secretRef: 31 | name: {{ .Values.configs.existingSecret }} 32 | {{- end }} 33 | command: 34 | - /bin/sh 35 | - -c 36 | - | 37 | apk update 38 | apk add curl 39 | apk add postgresql 40 | {{- if eq .Values.backup.destination "http" }} 41 | echo "Downloading latest backup" 42 | curl $RESTORE_URL --output /var/lib/backup/${DBNAME}.sql 43 | {{- end }} 44 | echo "Performing restore of db" 45 | ls -la 46 | psql -h $DBHOST -p $DBPORT -U $DBUSER < /var/lib/backup/${DBNAME}.sql 47 | echo "done" 48 | volumeMounts: 49 | - name: backup-storage 50 | mountPath: /var/lib/backup 51 | restartPolicy: Never 52 | volumes: 53 | - name: backup-storage 54 | {{- if eq .Values.backup.destination "pvc" }} 55 | persistentVolumeClaim: 56 | claimName: {{ default (printf "%s-%s" (include "firefly-db.fullname" .) "backup-storage-claim") .Values.backup.pvc.existingClaim }} 57 | {{- else }} 58 | emptyDir: {} 59 | {{- end }} 60 | -------------------------------------------------------------------------------- /kustomize/firefly-iii.yaml: -------------------------------------------------------------------------------- 1 | # Service to expose Firefly III on an available port in Kubernetes cluster 2 | # Assigned port can be seen with `kubectl get services firefly-iii` 3 | 4 | apiVersion: v1 5 | kind: Service 6 | metadata: 7 | name: firefly-iii 8 | labels: 9 | app: firefly-iii 10 | spec: 11 | clusterIP: None 12 | ports: 13 | - port: 8080 14 | selector: 15 | app: firefly-iii 16 | tier: frontend 17 | 18 | --- 19 | 20 | apiVersion: v1 21 | kind: PersistentVolumeClaim 22 | metadata: 23 | name: firefly-iii-upload-claim 24 | labels: 25 | app: firefly-iii 26 | spec: 27 | accessModes: 28 | - ReadWriteOnce 29 | resources: 30 | requests: 31 | storage: 9Gi 32 | 33 | --- 34 | 35 | apiVersion: apps/v1 36 | kind: Deployment 37 | metadata: 38 | name: firefly-iii 39 | labels: 40 | app: firefly-iii 41 | spec: 42 | selector: 43 | matchLabels: 44 | app: firefly-iii 45 | tier: frontend 46 | strategy: 47 | type: Recreate 48 | template: 49 | metadata: 50 | labels: 51 | app: firefly-iii 52 | tier: frontend 53 | spec: 54 | containers: 55 | - image: fireflyiii/core:version-6.4.9 56 | name: firefly-iii 57 | env: 58 | - name: APP_ENV 59 | value: "local" 60 | - name: APP_KEY 61 | valueFrom: 62 | secretKeyRef: 63 | name: firefly-iii-secrets 64 | key: app_key 65 | - name: DB_HOST 66 | value: firefly-iii-mysql 67 | - name: DB_CONNECTION 68 | value: mysql 69 | - name: DB_DATABASE 70 | value: "fireflyiii" 71 | - name: DB_USERNAME 72 | value: "root" 73 | - name: DB_PASSWORD 74 | valueFrom: 75 | secretKeyRef: 76 | name: firefly-iii-secrets 77 | key: db_password 78 | - name: TRUSTED_PROXIES 79 | value: "**" 80 | ports: 81 | - containerPort: 8080 82 | name: firefly-iii 83 | volumeMounts: 84 | - mountPath: "/var/www/html/storage/upload" 85 | name: firefly-iii-upload 86 | imagePullPolicy: Always 87 | volumes: 88 | - name: firefly-iii-upload 89 | persistentVolumeClaim: 90 | claimName: firefly-iii-upload-claim 91 | -------------------------------------------------------------------------------- /charts/firefly-db/Makefile: -------------------------------------------------------------------------------- 1 | SHELL := /bin/bash 2 | 3 | # >>> run this first when changing helm chart <<< 4 | # creates namespaces and packages chart 5 | default: 6 | @echo "Creating new package" 7 | helm package . 8 | @echo "creating debug namespace if not exists" 9 | kubectl create namespace debug --dry-run=client -o yaml | kubectl apply -f - 10 | @echo "creating dryrun namespace if not exists" 11 | kubectl create namespace dryrun --dry-run=client -o yaml | kubectl apply -f - 12 | @echo "creating firefly namespace if not exists" 13 | @echo "creating firefly namespace if not exists" 14 | kubectl create namespace firefly --dry-run=client -o yaml | kubectl apply -f - 15 | @echo "Done" 16 | 17 | # >>> to test integrety of chart <<< 18 | .PHONY: dryRun 19 | dryRun: 20 | @CANDIDATE="$(shell ls -d -- *.tgz |sort -n|tail -n 1)"; \ 21 | echo "making dry run for $${CANDIDATE}"; \ 22 | helm install --dry-run --debug firefly-db-debug $${CANDIDATE} --namespace=debug; 23 | 24 | # >>> DEBUG <<< 25 | .PHONY: installDebug 26 | installDebug: 27 | @CANDIDATE="$(shell ls -d -- *.tgz |sort -n|tail -n 1)"; \ 28 | echo "installing $${CANDIDATE}"; \ 29 | helm install firefly-db-debug $${CANDIDATE} -f debug.local.values.yaml --namespace=debug; 30 | @echo "Done" 31 | 32 | .PHONY: upgradeDebug 33 | upgradeDebug: 34 | @CANDIDATE="$(shell ls -d -- *.tgz |sort -n|tail -n 1)"; \ 35 | echo "upgrading $${CANDIDATE}"; \ 36 | helm upgrade firefly-db-debug $${CANDIDATE} -f debug.local.values.yaml --namespace=debug; 37 | @echo "Done" 38 | 39 | .PHONY: teardownDebug 40 | teardownDebug: 41 | @echo "Deleting firefly-db" 42 | helm delete firefly-db-debug --namespace=debug 43 | @echo "Done" 44 | 45 | # >>> PROD <<< 46 | .PHONY: install 47 | install: 48 | @CANDIDATE="$(shell ls -d -- *.tgz |sort -n|tail -n 1)"; \ 49 | echo "installing $${CANDIDATE}"; \ 50 | helm install firefly-db $${CANDIDATE} -f my.local.values.yaml --namespace=firefly; 51 | @echo "Done" 52 | 53 | .PHONY: upgrade 54 | upgrade: 55 | @CANDIDATE="$(shell ls -d -- *.tgz |sort -n|tail -n 1)"; \ 56 | echo "upgrading $${CANDIDATE}"; \ 57 | helm upgrade firefly-db $${CANDIDATE} -f my.local.values.yaml --namespace=firefly; 58 | @echo "Done" 59 | 60 | # >>> DELETE PROD <<< 61 | .PHONY: teardown 62 | teardown: 63 | @echo "Deleting firefly-db" 64 | helm delete firefly-db --namespace=firefly 65 | @echo "Done" -------------------------------------------------------------------------------- /charts/firefly-db/README.md: -------------------------------------------------------------------------------- 1 | # firefly-db 2 | 3 | ![Version: 0.2.9](https://img.shields.io/badge/Version-0.2.9-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) 4 | 5 | Installs a postgres db for Firefly III 6 | 7 | ## Maintainers 8 | 9 | | Name | Email | Url | 10 | | ---- | ------ | --- | 11 | | morremeyer | | | 12 | ## Source Code 13 | 14 | * 15 | 16 | ## Upgrading 17 | 18 | When a release introduces breaking changes, this section outlines the manual actions that need to be taken. 19 | 20 | ### From 0.0.2 to 0.0.3 21 | 22 | The storage class and access modes have been changed to match more setups without the need for configuration. If you want to keep the old settings, set the following values: 23 | 24 | ```yaml 25 | storage: 26 | class: nfs-client 27 | accessModes: ReadWriteMany 28 | ``` 29 | 30 | ## Values 31 | 32 | | Key | Type | Default | Description | 33 | |-----|------|---------|-------------| 34 | | backup.destination | string | `"pvc"` | | 35 | | backup.pvc.accessModes | string | `"ReadWriteOnce"` | | 36 | | backup.pvc.class | string | `nil` | | 37 | | backup.pvc.dataSize | string | `"1Gi"` | | 38 | | backup.pvc.existingClaim | string | `""` | Use an existing PersistentVolumeClaim, overrides values above | 39 | | backupSchedule | string | `"0 3 * * *"` | | 40 | | configs.BACKUP_URL | string | `""` | | 41 | | configs.DBHOST | string | `""` | | 42 | | configs.DBNAME | string | `"firefly"` | | 43 | | configs.DBPORT | string | `"5432"` | | 44 | | configs.DBUSER | string | `"firefly"` | | 45 | | configs.PGPASSWORD | string | `""` | | 46 | | configs.POSTGRES_HOST_AUTH_METHOD | string | `"trust"` | | 47 | | configs.POSTGRES_PASSWORD | string | `""` | | 48 | | configs.POSTGRES_USER | string | `"firefly"` | | 49 | | configs.RESTORE_URL | string | `""` | | 50 | | configs.TZ | string | `"Europe/Amsterdam"` | | 51 | | configs.existingSecret | string | `""` | Set this to the name of a secret to load environment variables from. If defined, values in the secret will override values in configs | 52 | | image.pullPolicy | string | `"IfNotPresent"` | | 53 | | image.repository | string | `"postgres"` | | 54 | | image.tag | string | `"10-alpine"` | | 55 | | nodeSelector | object | `{}` | | 56 | | storage.accessModes | string | `"ReadWriteOnce"` | | 57 | | storage.class | string | `nil` | | 58 | | storage.dataSize | string | `"1Gi"` | | 59 | | storage.existingClaim | string | `""` | Use an existing PersistentVolumeClaim, overrides values above | 60 | -------------------------------------------------------------------------------- /charts/README.md: -------------------------------------------------------------------------------- 1 | # Firefly III helm charts 2 | 3 | :information_source: We're working towards a 1.0.0 release of the **firefly-iii-stack** chart. The **firefly-iii** and **importer** charts are already released as 1.x. 4 | 5 | Installs Firefly III in kubernetes. 6 | 7 | ## Installation 8 | 9 | Add the helm repository with 10 | 11 | ```sh 12 | helm repo add firefly-iii https://firefly-iii.github.io/kubernetes 13 | helm repo update 14 | ``` 15 | 16 | The charts are then usable as e.g. `firefly-iii/firefly-iii-stack`: 17 | 18 | ```sh 19 | helm install firefly-iii firefly-iii/firefly-iii-stack 20 | ``` 21 | 22 | ## Anatomy 23 | 24 | This chart repository contains four charts: 25 | 26 | * [**firefly-iii-stack**](firefly-iii-stack) which is a wrapper chart around the other charts. If you're unsure which chart(s) to use, use this one. 27 | * [**firefly-iii**](firefly-iii) which installs the [Firefly III core application](https://github.com/firefly-iii/firefly-iii) 28 | * [**importer**](importer) which installs the [Firefly III data importer](https://github.com/firefly-iii/data-importer) 29 | * [**firefly-db**](firefly-db) which is _deprecated_ and installs a postgresql database to your cluster. It will be removed with version 1.0.0 of the firefly-stack chart and replaced by [bitnami/postgresql](https://github.com/bitnami/charts/tree/master/bitnami/postgresql) 30 | 31 | ## Configuration 32 | 33 | Each chart contains a `values.yaml` file that is set up with best practices in mind. If you want to override them, specify your own values file for the helm command. 34 | 35 | Note that if you use the firefly-iii-stack chart, you'll have to put the values in the respective key, e.g. `firefly-iii.config` for the `config` values of the [firefly-iii](firefly-iii) chart. 36 | 37 | ## Development and testing 38 | 39 | For the firefly-iii-stack chart, you need to [override the chart dependencies locally](firefly-iii-stack/README.md#dependency-chart-overrides) to develop it on your machine. 40 | 41 | Please document values with `# -- ` comments so that helm-docs can automatically pick them up for the README. 42 | 43 | When introducing breaking changes, please document them in the `README.md.gotmpl` file of the respective chart. 44 | 45 | ### Versioning 46 | 47 | Helm charts use semantic versioning. For the charts in this repository, we only use the `[MAJOR].[MINOR].[PATCH]` syntax without any pre-releases. 48 | 49 | Please bump as follows: 50 | 51 | * Major version for breaking changes (this includes updates of default values as users may need to manually update their values) 52 | * Minor version when you add features 53 | * Patch version for bug fixes and documentation updates 54 | 55 | For the automatic releasing and linting to work, do not manually update the `firefly-iii-stack` to use new dependency versions in the same PR as this will fail validation and releasing. 56 | -------------------------------------------------------------------------------- /charts/firefly-iii-stack/README.md.gotmpl: -------------------------------------------------------------------------------- 1 | {{ template "chart.header" . }} 2 | {{ template "chart.deprecationWarning" . }} 3 | {{ template "chart.badgesSection" . }} 4 | 5 | {{ template "chart.description" . }} 6 | {{ template "chart.homepageLine" . }} 7 | {{ template "chart.maintainersSection" . }} 8 | {{ template "chart.sourcesSection" . }} 9 | {{ template "chart.requirementsSection" . }} 10 | 11 | ## Upgrading 12 | 13 | When a release introduces breaking changes, this section outlines the manual actions that need to be taken. 14 | 15 | ### From 0.4.0 to 0.5.0 16 | 17 | No breaking changes in this release, but you can now use the helm repository directly from https://firefly-iii.github.io/kubernetes/. 18 | 19 | ### From 0.1.0 to 0.2.0 20 | 21 | The **firefely** wrapper chart has been renamed to **firefly-iii-stack**. All charts are now contained directly in the `charts` directory, following best practices for chart repositories. 22 | 23 | ### From 0.0.5 to 0.1.0 24 | 25 | The `firefly-iii` chart has been overhauled and contains breaking changes. Please check out [the charts upgrade notes](charts/firefly-iii/README.md#from-004-to-100). 26 | 27 | ### From 0.0.4 to 0.0.5 28 | 29 | The `firefly-csv` chart has been removed as the CSV importer has been integrated into the importer. Please check out the new [`importer` chart](charts/importer/README.md). 30 | 31 | ### From 0.0.3 to 0.0.4 32 | 33 | The storage class and access modes have been changed to match more setups without the need for configuration. If you want to keep the old settings, set the following values: 34 | 35 | ```yaml 36 | firefly-iii: 37 | storage: 38 | class: nfs-client 39 | accessModes: ReadWriteMany 40 | 41 | firefly-csv: 42 | storage: 43 | class: nfs-client 44 | accessModes: ReadWriteMany 45 | 46 | firefly-db: 47 | storage: 48 | class: nfs-client 49 | accessModes: ReadWriteMany 50 | ``` 51 | 52 | ### From 0.0.2 to 0.0.3 53 | 54 | The `firefly-iii` and `firefly-csv` charts have been updated and now support configuring ingress annotations. 55 | 56 | To keep the old annotations, add the following values: 57 | 58 | ```yaml 59 | firefly-iii: 60 | ingress: 61 | annotations: 62 | kubernetes.io/ingress.class: "nginx" 63 | nginx.ingress.kubernetes.io/proxy-buffer-size: "16k" 64 | 65 | firefly-csv: 66 | ingress: 67 | annotations: 68 | kubernetes.io/ingress.class: "nginx" 69 | nginx.org/client-max-body-size: "0" 70 | nginx.ingress.kubernetes.io/proxy-buffer-size: "16k" 71 | ``` 72 | 73 | ## Development and testing 74 | 75 | ### Dependency chart overrides 76 | 77 | Unfortunately, helm does not yet have a neat mechanism to dynamically override chart dependencies for local development/testing. 78 | 79 | Therefore, you'll need to override the dependencies manually for local testing and development. To do so, you need to update the `Chart.yaml` file. 80 | 81 | For every dependency, replace `repository: https://firefly-iii.github.io/kubernetes/` with `repository: file://../${dependency_chart_name}`. 82 | 83 | {{ template "chart.valuesSection" . }} 84 | -------------------------------------------------------------------------------- /charts/firefly-iii/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* 2 | Expand the name of the chart. 3 | */}} 4 | {{- define "firefly-iii.name" -}} 5 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} 6 | {{- end }} 7 | 8 | {{/* 9 | Create a default fully qualified app name. 10 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 11 | If release name contains chart name it will be used as a full name. 12 | */}} 13 | {{- define "firefly-iii.fullname" -}} 14 | {{- if .Values.fullnameOverride }} 15 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} 16 | {{- else }} 17 | {{- $name := default .Chart.Name .Values.nameOverride }} 18 | {{- if contains $name .Release.Name }} 19 | {{- .Release.Name | trunc 63 | trimSuffix "-" }} 20 | {{- else }} 21 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} 22 | {{- end }} 23 | {{- end }} 24 | {{- end }} 25 | 26 | {{/* 27 | Create chart name and version as used by the chart label. 28 | */}} 29 | {{- define "firefly-iii.chart" -}} 30 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} 31 | {{- end }} 32 | 33 | {{/* 34 | Common labels 35 | */}} 36 | {{- define "firefly-iii.labels" -}} 37 | helm.sh/chart: {{ include "firefly-iii.chart" . }} 38 | {{ include "firefly-iii.selectorLabels" . }} 39 | {{- if .Chart.AppVersion }} 40 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 41 | {{- end }} 42 | app.kubernetes.io/managed-by: {{ .Release.Service }} 43 | {{- end }} 44 | 45 | {{/* 46 | Selector labels 47 | */}} 48 | {{- define "firefly-iii.selectorLabels" -}} 49 | app.kubernetes.io/name: {{ include "firefly-iii.name" . }} 50 | app.kubernetes.io/instance: {{ .Release.Name }} 51 | {{- end }} 52 | 53 | {{/* 54 | Create the name of the service account to use 55 | */}} 56 | {{- define "firefly-iii.serviceAccountName" -}} 57 | {{- if .Values.serviceAccount.create }} 58 | {{- default (include "firefly-iii.fullname" .) .Values.serviceAccount.name }} 59 | {{- else }} 60 | {{- default "default" .Values.serviceAccount.name }} 61 | {{- end }} 62 | {{- end }} 63 | 64 | 65 | {{/* 66 | Create the APP_KEY used for encryption, should be random 32 characters. 67 | In order to NOT create a new key for each upgrade a check to the secret is done, 68 | if secret exists, use previous values, if not, create a new key 69 | */}} 70 | {{- define "firefly-iii.app-key" -}} 71 | {{- if .Values.secrets.appKey -}} 72 | {{ include "firefly-iii.validate-app-key" . | required "appKey needs to be exactly 32 characters" }} 73 | {{- else -}} 74 | {{- $secret_key := lookup "v1" "Secret" .Release.Namespace (printf "%s-app-key" ( include "firefly-iii.fullname" . )) -}} 75 | {{- if $secret_key -}} 76 | {{ $secret_key.data.APP_KEY | b64dec }} 77 | {{- else -}} 78 | {{- randAlphaNum 32 | nospace -}} 79 | {{- end }} 80 | {{- end }} 81 | {{- end }} 82 | 83 | {{/* 84 | Validate if length of APP_KEY is 32 characters 85 | */}} 86 | {{- define "firefly-iii.validate-app-key" -}} 87 | {{ $length := len .Values.secrets.appKey }} 88 | {{- if eq 32 $length -}} 89 | {{- .Values.secrets.appKey -}} 90 | {{- end -}} 91 | {{- end -}} 92 | -------------------------------------------------------------------------------- /.github/code_of_conduct.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at thegrumpydictator@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Firefly III Kubernetes resources 2 | 3 | [![Packagist](https://img.shields.io/packagist/v/grumpydictator/firefly-iii.svg?style=flat-square)](https://packagist.org/packages/grumpydictator/firefly-iii) 4 | [![License](https://img.shields.io/github/license/firefly-iii/firefly-iii.svg?style=flat-square])](https://www.gnu.org/licenses/agpl-3.0.html) 5 | [![Donate using Patreon](https://img.shields.io/badge/donate-%40JC5-green?logo=patreon&style=flat-square)](https://www.patreon.com/jc5) 6 | [![Donate using GitHub](https://img.shields.io/badge/donate-GitHub-green?logo=github&style=flat-square)](https://github.com/sponsors/JC5) 7 | 8 | 9 |
10 |

11 | 12 | Firefly III 13 | 14 |

15 |

Firefly III

16 | 17 |

18 | A free and open source personal finance manager 19 |
20 |

21 | 22 | 23 | This repository contains the Kubernetes resources needed to deploy Firefly III, a database and tooling for Firefly III. 24 | 25 | ## Deployment 26 | 27 | ### Plain yaml files or kustomize 28 | 29 | * [mysql.yaml](kustomize/mysql.yaml), to create a MySQL database. 30 | * [firefly-iii.yaml](kustomize/firefly-iii.yaml), to run Firefly III. 31 | * [kustomization.yaml](kustomize/kustomization.yaml), containing references to both and the necessary secrets. 32 | 33 | ### helm 34 | 35 | Check out the helm charts in [`charts`](charts/README.md). A chart repository is available at `https://firefly-iii.github.io/kubernetes/`. 36 | 37 | ## References 38 | 39 | Here are some links for your reading pleasure. 40 | 41 | - [Firefly III on GitHub](https://github.com/firefly-iii/firefly-iii) 42 | - [Documentation](https://docs.firefly-iii.org/installation/k8n) 43 | - [Extra instructions and information](https://github.com/creylopez/ffiiimacosk8s) for MacOS. 44 | 45 | Please open any issues you have [in the main repository](https://github.com/firefly-iii/firefly-iii). 46 | 47 | 48 | 49 | ## Do you need help, or do you want to get in touch? 50 | 51 | Do you want to contact me? You can email me at [james@firefly-iii.org](mailto:james@firefly-iii.org) or get in touch through one of the following support channels: 52 | 53 | - [GitHub Discussions](https://github.com/firefly-iii/firefly-iii/discussions/) for questions and support 54 | - [Gitter.im](https://gitter.im/firefly-iii/firefly-iii) for a good chat and a quick answer 55 | - [GitHub Issues](https://github.com/firefly-iii/firefly-iii/issues) for bugs and issues 56 | - Mastodon for news and updates 57 | 58 | 59 | 60 | 61 | 62 | ## Support the development of Firefly III 63 | 64 | If you like Firefly III and if it helps you save lots of money, why not send me a dime for every dollar saved! 🥳 65 | 66 | OK that was a joke. If you feel Firefly III made your life better, please consider contributing as a sponsor. Please check out my [Patreon](https://www.patreon.com/jc5) and [GitHub Sponsors](https://github.com/sponsors/JC5) page for more information. You can also [buy me a ☕️ coffee at ko-fi.com](https://ko-fi.com/Q5Q5R4SH1). Thank you for your consideration. 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /.github/workflows/lint-and-release.yml: -------------------------------------------------------------------------------- 1 | name: Lint and release charts 2 | 3 | on: 4 | pull_request: 5 | push: 6 | branches: 7 | - main 8 | 9 | jobs: 10 | lint-firefly-db: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@v2 15 | with: 16 | fetch-depth: 0 17 | - name: Set up Helm 18 | uses: azure/setup-helm@v4 19 | - uses: actions/setup-python@v2 20 | with: 21 | python-version: "3.10" 22 | - name: Set up chart-testing 23 | uses: helm/chart-testing-action@v2.3.1 24 | - name: Run chart-testing (lint) 25 | run: ct lint --config ct.yaml --charts charts/firefly-db 26 | 27 | lint-firefly-iii: 28 | runs-on: ubuntu-latest 29 | steps: 30 | - name: Checkout 31 | uses: actions/checkout@v2 32 | with: 33 | fetch-depth: 0 34 | - name: Set up Helm 35 | uses: azure/setup-helm@v4 36 | - uses: actions/setup-python@v2 37 | with: 38 | python-version: "3.10" 39 | - name: Set up chart-testing 40 | uses: helm/chart-testing-action@v2.3.1 41 | - name: Run chart-testing (lint) 42 | run: ct lint --config ct.yaml --charts charts/firefly-iii 43 | 44 | lint-importer: 45 | runs-on: ubuntu-latest 46 | steps: 47 | - name: Checkout 48 | uses: actions/checkout@v2 49 | with: 50 | fetch-depth: 0 51 | - name: Set up Helm 52 | uses: azure/setup-helm@v4 53 | - uses: actions/setup-python@v2 54 | with: 55 | python-version: "3.10" 56 | - name: Set up chart-testing 57 | uses: helm/chart-testing-action@v2.3.1 58 | - name: Run chart-testing (lint) 59 | run: ct lint --config ct.yaml --charts charts/importer 60 | 61 | lint-stack: 62 | needs: [lint-firefly-db, lint-firefly-iii, lint-importer] 63 | runs-on: ubuntu-latest 64 | steps: 65 | - name: Checkout 66 | uses: actions/checkout@v2 67 | with: 68 | fetch-depth: 0 69 | - name: Set up Helm 70 | uses: azure/setup-helm@v4 71 | - uses: actions/setup-python@v2 72 | with: 73 | python-version: "3.10" 74 | - name: Set up chart-testing 75 | uses: helm/chart-testing-action@v2.3.1 76 | - name: Run chart-testing (lint) 77 | run: ct lint --config ct.yaml --charts charts/firefly-iii-stack 78 | 79 | 80 | release: 81 | if: ${{ github.ref == 'refs/heads/main' }} 82 | needs: 83 | - lint-stack 84 | runs-on: ubuntu-latest 85 | steps: 86 | - name: Checkout 87 | uses: actions/checkout@v2 88 | with: 89 | fetch-depth: 0 90 | 91 | - name: Configure Git 92 | run: | 93 | git config user.name "$GITHUB_ACTOR" 94 | git config user.email "$GITHUB_ACTOR@users.noreply.github.com" 95 | 96 | - name: Install Helm 97 | uses: azure/setup-helm@v1 98 | with: 99 | # renovate: datasource=github-releases depName=helm/helm 100 | version: v3.8.0 101 | 102 | - name: Run chart-releaser 103 | uses: helm/chart-releaser-action@v1.7.0 104 | env: 105 | CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 106 | 107 | # Skip upload of existing charts. This is useful when not bumping version numbers 108 | # for simple documentation updates 109 | CR_SKIP_EXISTING: true 110 | -------------------------------------------------------------------------------- /charts/importer/values.yaml: -------------------------------------------------------------------------------- 1 | replicaCount: 1 2 | 3 | # -- The proxies that are trusted by the importer 4 | trustedProxies: "**" 5 | 6 | fireflyiii: 7 | # -- The URL at which Firefly III is available. If you change this value, click the "Reauthenticate" button on the importer after opening it! 8 | url: "http://firefly-firefly-iii:80" 9 | 10 | # -- The URL at which you access Firefly III. Check https://docs.firefly-iii.org/data-importer/install/configure/#configure-fidi to find out if you should set this. 11 | vanityUrl: "" 12 | 13 | auth: 14 | # -- If you specify an existingSecret, it has to have the accessToken in a .spec.data.accessToken 15 | existingSecret: "" 16 | 17 | # -- The access token in plain text 18 | accessToken: "" 19 | 20 | # -- Environment variables for the importer. See docs at: https://github.com/firefly-iii/data-importer/blob/main/.env.example 21 | config: 22 | # -- Set this to the name of a secret to load environment variables from. If defined, values in the secret will override values in config.env 23 | existingSecret: "" 24 | 25 | # -- Set environment variables from configMaps or Secrets 26 | envValueFrom: {} 27 | 28 | # -- Directly defined environment variables. Use this for non-secret configuration values. 29 | env: 30 | IGNORE_DUPLICATE_ERRORS: "false" 31 | TZ: "Europe/Amsterdam" 32 | 33 | # -- A list of files with a mountPath, a file name and the file's content. Files are stored as a secret. 34 | files: 35 | - mountPath: /var/www/html/storage/configurations 36 | name: test.txt 37 | content: | 38 | This is a test file with some content 39 | 40 | # -- Configure additional mounts for the pod. Value is a list of VolumeMount specs, see https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#volumemount-v1-core 41 | additionalVolumeMounts: [] 42 | 43 | # -- Configure additional volumes for the Pod. Value is a list of Volume specs, see https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#volume-v1-core 44 | additionalVolumes: [] 45 | 46 | image: 47 | repository: fireflyiii/data-importer 48 | pullPolicy: IfNotPresent 49 | tag: "version-1.9.1" 50 | 51 | imagePullSecrets: [] 52 | nameOverride: "" 53 | fullnameOverride: "" 54 | 55 | podAnnotations: {} 56 | 57 | podSecurityContext: {} 58 | # fsGroup: 2000 59 | 60 | securityContext: {} 61 | # capabilities: 62 | # drop: 63 | # - ALL 64 | # readOnlyRootFilesystem: true 65 | # runAsNonRoot: true 66 | # runAsUser: 1000 67 | 68 | service: 69 | type: ClusterIP 70 | port: 80 71 | 72 | ingress: 73 | enabled: false 74 | className: "" 75 | annotations: {} 76 | # kubernetes.io/ingress.class: nginx 77 | # kubernetes.io/tls-acme: "true" 78 | hosts: 79 | - chart-example.local 80 | tls: [] 81 | # - secretName: chart-example-tls 82 | # hosts: 83 | # - chart-example.local 84 | 85 | resources: {} 86 | # We usually recommend not to specify default resources and to leave this as a conscious 87 | # choice for the user. This also increases chances charts run on environments with little 88 | # resources, such as Minikube. If you do want to specify resources, uncomment the following 89 | # lines, adjust them as necessary, and remove the curly braces after 'resources:'. 90 | # limits: 91 | # cpu: 100m 92 | # memory: 128Mi 93 | # requests: 94 | # cpu: 100m 95 | # memory: 128Mi 96 | 97 | nodeSelector: {} 98 | 99 | tolerations: [] 100 | 101 | affinity: {} 102 | -------------------------------------------------------------------------------- /charts/firefly-iii/README.md.gotmpl: -------------------------------------------------------------------------------- 1 | {{ template "chart.header" . }} 2 | {{ template "chart.deprecationWarning" . }} 3 | {{ template "chart.badgesSection" . }} 4 | 5 | {{ template "chart.description" . }} 6 | {{ template "chart.homepageLine" . }} 7 | {{ template "chart.maintainersSection" . }} 8 | {{ template "chart.sourcesSection" . }} 9 | {{ template "chart.requirementsSection" . }} 10 | 11 | ## Setting environment variables from additional ConfigMaps and Secrets 12 | 13 | This enables a simplified syntax to set envirnoment variables from a ConfigMap or Secret: 14 | 15 | ```yaml 16 | envValueFrom: 17 | USER: 18 | secretKeyRef: 19 | name: secret-name 20 | key: user 21 | ``` 22 | 23 | ## Upgrading 24 | 25 | When a release introduces breaking changes, this section outlines the manual actions that need to be taken. 26 | 27 | ### From 0.0.4 to 1.0.0 28 | 29 | This version bump is a full rework of the chart to be in line with current helm best practices and to add configurability. See the subsections for all changes. 30 | 31 | A cronjob has been added to support [Firefly III features that need it](https://docs.firefly-iii.org/firefly-iii/advanced-installation/cron/). It is disabled by default, set `cronjob.enabled` to true to enable it. Please note that you need to specify `cronjob.auth.token` or `cronjob.auth.existingSecret` so that the job is actually deployed an can run. If you specify an existingSecret, it needs to have the token in the field `token`. 32 | 33 | #### Resources 34 | 35 | The PVC has been renamed. You therefore need to manually back up and restore the upload data or retain and reclaim the PV with the new PVC. As this is highly dependant on your Kubernetes distribution and provider, instructions for the latter can't be generalized. 36 | 37 | To backup and restore your files easily, use `kubectl cp $FIREFLY_POD_NAME:/var/www/html/storage/upload $LOCAL_BACKUP_DIR`, apply the changes and then reverse the process by running `kubectl cp "${LOCAL_BACKUP_DIR}/*" $FIREFLY_POD_NAME:/var/www/html/storage/upload/`. 38 | 39 | #### values.yaml 40 | 41 | The configuration has changed as follows: 42 | 43 | * `storage` has been moved to `persistence`. There's a new `persistence.enabled` value that is `true` by default. 44 | * `storage.dataSize` has been moved to `persistence.storage`. 45 | * `hostName` has moved to a list in `ingress.hosts` 46 | * The ingress is disabled by default. Set `ingress.enabled` to `true` to enable it 47 | * `configs` has moved to `config.env` 48 | * A new key `config.existingSecret` has been added. It references a secret where you can store Firefly III configuration environment variables. Environment variables specified in the secret override the ones in `config.env`. 49 | 50 | #### Labels 51 | 52 | The pod label keys have changed as follows: 53 | 54 | * `app` has been replaced by `app.kubernetes.io/name` 55 | * `chart` has been replaced by `helm.sh/chart` 56 | * `release` has been replaced by `app.kubernetes.io/instance` 57 | * `heritage` has been replaced by `app.kubernetes.io/managed-by` 58 | 59 | ### From 0.0.3 to 0.0.4 60 | 61 | The storage class and access modes have been changed to match more setups without the need for configuration. If you want to keep the old settings, set the following values: 62 | 63 | ```yaml 64 | storage: 65 | class: nfs-client 66 | accessModes: ReadWriteMany 67 | ``` 68 | 69 | ### From 0.0.2 to 0.0.3 70 | 71 | The Ingress annotations have been made configurable. To keep the annotations set in 0.0.2, add the following to your values: 72 | 73 | ```yaml 74 | ingress: 75 | annotations: 76 | kubernetes.io/ingress.class: "nginx" 77 | nginx.ingress.kubernetes.io/proxy-buffer-size: "16k" 78 | ``` 79 | 80 | {{ template "chart.valuesSection" . }} 81 | -------------------------------------------------------------------------------- /.github/workflows/cleanup.yml: -------------------------------------------------------------------------------- 1 | # This workflow prunes old workflow runs for an entire repository. 2 | 3 | name: "Chore - Prune old builds" 4 | 5 | permissions: 6 | actions: write 7 | 8 | on: 9 | schedule: 10 | - cron: '0 1 * * *' 11 | workflow_dispatch: 12 | jobs: 13 | prune: 14 | runs-on: ubuntu-latest 15 | timeout-minutes: 10 16 | steps: 17 | - name: Prune cancelled/skipped runs 18 | uses: actions/github-script@v7 19 | with: 20 | github-token: ${{ secrets.GITHUB_TOKEN }} 21 | script: | 22 | const cancelled = await github.rest.actions.listWorkflowRunsForRepo({ 23 | owner: context.repo.owner, 24 | per_page: 100, 25 | repo: context.repo.repo, 26 | status: 'cancelled', 27 | }); 28 | 29 | const skipped = await github.rest.actions.listWorkflowRunsForRepo({ 30 | owner: context.repo.owner, 31 | per_page: 100, 32 | repo: context.repo.repo, 33 | status: 'skipped', 34 | }); 35 | 36 | for (const response of [cancelled, skipped]) { 37 | for (const run of response.data.workflow_runs) { 38 | console.log(`Run id ${run.id} of '${run.name}' is a cancelled/skipped run. Deleting...`); 39 | await github.rest.actions.deleteWorkflowRun({ 40 | owner: context.repo.owner, 41 | repo: context.repo.repo, 42 | run_id: run.id 43 | }); 44 | } 45 | } 46 | 47 | - name: Prune runs older than 3 days 48 | uses: actions/github-script@v7 49 | with: 50 | github-token: ${{ secrets.GITHUB_TOKEN }} 51 | script: | 52 | const days_to_expiration = 3; 53 | const ms_in_day = 86400000; 54 | const now = Date.now(); 55 | const pages = 5; 56 | 57 | // we don't want to prune old runs from test.yml 58 | // because we track the duration of runs over time 59 | 60 | const workflows = [ 61 | 'cleanup.yml', 62 | 'helm-docs.yml', 63 | 'label.yml', 64 | 'lint-and-release.yml', 65 | 'transfer.yml' 66 | ] 67 | 68 | let runs_to_delete = []; 69 | 70 | for (const workflow of workflows) { 71 | for (let page = 0; page < pages; page += 1) { 72 | let response = await github.rest.actions.listWorkflowRuns({ 73 | owner: context.repo.owner, 74 | page: page, 75 | per_page: 100, 76 | repo: context.repo.repo, 77 | workflow_id: workflow 78 | }); 79 | 80 | if (response.data.workflow_runs.length > 0) { 81 | for (const run of response.data.workflow_runs) { 82 | if (now - Date.parse(run.created_at) > ms_in_day * days_to_expiration) { 83 | runs_to_delete.push([run.id, run.name]); 84 | } 85 | } 86 | } 87 | } 88 | } 89 | 90 | for (const run of runs_to_delete) { 91 | console.log(`Run id ${run[0]} of '${run[1]}' is older than ${days_to_expiration} days. Deleting...`); 92 | try { 93 | await github.rest.actions.deleteWorkflowRun({ 94 | owner: context.repo.owner, 95 | repo: context.repo.repo, 96 | run_id: run[0] 97 | }); 98 | } catch (error) { 99 | // ignore errors 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /charts/firefly-iii/templates/cronjob.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.cronjob.enabled }} 2 | {{- if or (.Values.cronjob.auth.token) (.Values.cronjob.auth.existingSecret) }} 3 | {{- if .Capabilities.APIVersions.Has "batch/v1" }} 4 | apiVersion: batch/v1 5 | {{- else -}} 6 | apiVersion: batch/v1beta1 7 | {{- end }} 8 | kind: CronJob 9 | metadata: 10 | name: {{ include "firefly-iii.fullname" . }}-cronjob 11 | labels: 12 | {{- include "firefly-iii.labels" . | nindent 4 }} 13 | {{- with .Values.labels }} 14 | {{- toYaml . | nindent 4 }} 15 | {{- end }} 16 | annotations: 17 | {{- with .Values.cronjob.annotations }} 18 | {{- toYaml . | nindent 4 }} 19 | {{- end }} 20 | spec: 21 | {{- with .Values.cronjob.successfulJobsHistoryLimit }} 22 | successfulJobsHistoryLimit: {{ . }} 23 | {{- end }} 24 | {{- with .Values.cronjob.failedJobsHistoryLimit }} 25 | failedJobsHistoryLimit: {{ . }} 26 | {{- end }} 27 | schedule: "{{ .Values.cronjob.schedule }}" 28 | jobTemplate: 29 | spec: 30 | template: 31 | metadata: 32 | {{- with .Values.cronjob.podAnnotations }} 33 | annotations: {{- toYaml . | nindent 12 }} 34 | {{- end }} 35 | labels: {{- include "firefly-iii.selectorLabels" . | nindent 12 }} 36 | spec: 37 | restartPolicy: {{ .Values.cronjob.restartPolicy }} 38 | {{- with .Values.cronjob.imagePullSecrets }} 39 | imagePullSecrets: {{- toYaml . | nindent 12 }} 40 | {{- end }} 41 | {{- with .Values.cronjob.podSecurityContext }} 42 | securityContext: {{- toYaml . | nindent 12 }} 43 | {{- end }} 44 | containers: 45 | - name: {{ .Chart.Name }}-cronjob 46 | {{- with .Values.cronjob.securityContext }} 47 | securityContext: {{- toYaml . | nindent 16 }} 48 | {{- end }} 49 | {{- with .Values.cronjob.image }} 50 | image: "{{ coalesce $.Values.global.image.registry .registry }}/{{ .repository }}:{{ .tag }}" 51 | imagePullPolicy: {{ coalesce $.Values.global.image.pullPolicy .pullPolicy }} 52 | {{- end }} 53 | {{- /* Check if both the token and the existingSecret are defined and fail (this would lead to invalid configuration) */ -}} 54 | {{- if and (.Values.cronjob.auth.token) (.Values.cronjob.auth.existingSecret) }} 55 | {{- fail "You must only define one of .Values.cronjob.auth.token or .Values.cronjob.auth.existingSecret, not both!" }} 56 | {{- end }} 57 | env: 58 | - name: FIREFLY_III_TOKEN 59 | {{- if .Values.cronjob.auth.token }} 60 | value: {{ .Values.cronjob.auth.token }} 61 | {{- end }} 62 | {{- if .Values.cronjob.auth.existingSecret }} 63 | valueFrom: 64 | secretKeyRef: 65 | name: {{ .Values.cronjob.auth.existingSecret }} 66 | key: {{ .Values.cronjob.auth.secretKey }} 67 | {{- end }} 68 | command: 69 | - /usr/bin/curl 70 | args: 71 | - --silent 72 | - --show-error 73 | - --fail 74 | - "http://{{ include "firefly-iii.fullname" . }}/api/v1/cron/$(FIREFLY_III_TOKEN)" 75 | {{- with .Values.cronjob.resources }} 76 | resources: {{- toYaml . | nindent 16 }} 77 | {{- end }} 78 | {{- with .Values.cronjob.nodeSelector }} 79 | nodeSelector: {{- toYaml . | nindent 12 }} 80 | {{- end }} 81 | {{- with .Values.cronjob.affinity }} 82 | affinity: {{- toYaml . | nindent 12 }} 83 | {{- end }} 84 | {{- with .Values.cronjob.tolerations }} 85 | tolerations: {{- toYaml . | nindent 12 }} 86 | {{- end }} 87 | {{- end }} 88 | {{- end }} 89 | -------------------------------------------------------------------------------- /charts/importer/templates/deployment.yaml: -------------------------------------------------------------------------------- 1 | {{- $defaultSecretName := include "importer.fullname" . -}} 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: {{ include "importer.fullname" . }} 6 | labels: 7 | {{- include "importer.labels" . | nindent 4 }} 8 | spec: 9 | replicas: {{ .Values.replicaCount }} 10 | selector: 11 | matchLabels: 12 | {{- include "importer.selectorLabels" . | nindent 6 }} 13 | template: 14 | metadata: 15 | {{- with .Values.podAnnotations }} 16 | annotations: 17 | {{- toYaml . | nindent 8 }} 18 | {{- end }} 19 | labels: 20 | {{- include "importer.selectorLabels" . | nindent 8 }} 21 | spec: 22 | {{- with .Values.imagePullSecrets }} 23 | imagePullSecrets: 24 | {{- toYaml . | nindent 8 }} 25 | {{- end }} 26 | {{- with .Values.podSecurityContext }} 27 | securityContext: 28 | {{- toYaml . | nindent 8 }} 29 | {{- end }} 30 | containers: 31 | - name: {{ .Chart.Name }} 32 | {{- with .Values.securityContext }} 33 | securityContext: 34 | {{- toYaml . | nindent 12 }} 35 | {{- end }} 36 | image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" 37 | imagePullPolicy: {{ .Values.image.pullPolicy }} 38 | env: 39 | - name: FIREFLY_III_ACCESS_TOKEN 40 | valueFrom: 41 | secretKeyRef: 42 | name: {{ .Values.fireflyiii.auth.existingSecret | default $defaultSecretName }} 43 | key: accessToken 44 | - name: FIREFLY_III_URL 45 | value: {{ .Values.fireflyiii.url }} 46 | {{- if .Values.fireflyiii.vanityUrl }} 47 | - name: VANITY_URL 48 | value: {{ .Values.fireflyiii.vanityUrl }} 49 | {{- end }} 50 | - name: TRUSTED_PROXIES 51 | value: {{ .Values.trustedProxies | quote }} 52 | {{- if or .Values.config.envValueFrom }} 53 | {{- range $key, $value := .Values.config.envValueFrom }} 54 | - name: {{ $key }} 55 | valueFrom: {{- $value | toYaml | nindent 16 }} 56 | {{- end }} 57 | {{- end }} 58 | {{- if or (.Values.config.env) (.Values.config.existingSecret) }} 59 | envFrom: 60 | {{- if .Values.config.env }} 61 | - configMapRef: 62 | name: {{ template "importer.fullname" . }} 63 | {{- end }} 64 | {{- if .Values.config.existingSecret }} 65 | - secretRef: 66 | name: {{ .Values.config.existingSecret }} 67 | {{- end }} 68 | {{- end }} 69 | {{- if or .Values.config.files .Values.additionalVolumes }} 70 | volumeMounts: 71 | {{- with .Values.additionalVolumeMounts }} 72 | {{- toYaml . | nindent 12 }} 73 | {{- end }} 74 | {{- if .Values.config.files }} 75 | {{- range .Values.config.files }} 76 | - name: files 77 | mountPath: {{ .mountPath }}/{{ .name }} 78 | subPath: {{ .name }} 79 | {{- end }} 80 | {{- end }} 81 | {{- end }} 82 | ports: 83 | - name: http 84 | containerPort: 8080 85 | protocol: TCP 86 | livenessProbe: 87 | tcpSocket: 88 | port: http 89 | readinessProbe: 90 | tcpSocket: 91 | port: http 92 | {{- with .Values.resources }} 93 | resources: 94 | {{- toYaml . | nindent 12 }} 95 | {{- end }} 96 | {{- with .Values.nodeSelector }} 97 | nodeSelector: 98 | {{- toYaml . | nindent 8 }} 99 | {{- end }} 100 | {{- with .Values.affinity }} 101 | affinity: 102 | {{- toYaml . | nindent 8 }} 103 | {{- end }} 104 | {{- with .Values.tolerations }} 105 | tolerations: 106 | {{- toYaml . | nindent 8 }} 107 | {{- end }} 108 | {{- if or .Values.config.files .Values.additionalVolumes }} 109 | volumes: 110 | - name: files 111 | secret: 112 | secretName: {{ include "importer.fullname" . }}-files 113 | {{- with .Values.additionalVolumes }} 114 | {{- toYaml . | nindent 8 }} 115 | {{- end }} 116 | {{- end }} 117 | -------------------------------------------------------------------------------- /charts/importer/README.md: -------------------------------------------------------------------------------- 1 | # importer 2 | 3 | ![Version: 1.5.1](https://img.shields.io/badge/Version-1.5.1-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) 4 | 5 | Deploys the importer chart for Firefly III 6 | **Homepage:** 7 | ## Maintainers 8 | 9 | | Name | Email | Url | 10 | | ---- | ------ | --- | 11 | | morremeyer | | | 12 | ## Source Code 13 | 14 | * 15 | 16 | ## Setup 17 | 18 | :warning: When enabling the ingress, be aware that the importer does not have any authentication. You are responsible to configure authentication at the ingress level 19 | 20 | There are some values that you should check before installing this chart: 21 | 22 | * `trustedProxies` (default: `"**"`): The proxies that are trusted by the importer 23 | * `fireflyiii.url` (default: `"http://firefly-firefly-iii:8080"`): The URL at which Firefly III is available 24 | 25 | For authentication, use `fireflyiii.auth.existingSecret` if you have an existing Secret with `data.accessToken` specified. 26 | When you set `fireflyiii.auth.accessToken`, be aware that this is a secret and should not be commited to a repository. 27 | 28 | ## Upgrading 29 | 30 | When a release introduces breaking changes, this section outlines the manual actions that need to be taken. 31 | 32 | ## Values 33 | 34 | | Key | Type | Default | Description | 35 | |-----|------|---------|-------------| 36 | | additionalVolumeMounts | list | `[]` | Configure additional mounts for the pod. Value is a list of VolumeMount specs, see https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#volumemount-v1-core | 37 | | additionalVolumes | list | `[]` | Configure additional volumes for the Pod. Value is a list of Volume specs, see https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#volume-v1-core | 38 | | affinity | object | `{}` | | 39 | | config | object | `{"env":{"IGNORE_DUPLICATE_ERRORS":"false","TZ":"Europe/Amsterdam"},"envValueFrom":{},"existingSecret":"","files":[{"content":"This is a test file with some content\n","mountPath":"/var/www/html/storage/configurations","name":"test.txt"}]}` | Environment variables for the importer. See docs at: https://github.com/firefly-iii/data-importer/blob/main/.env.example | 40 | | config.env | object | `{"IGNORE_DUPLICATE_ERRORS":"false","TZ":"Europe/Amsterdam"}` | Directly defined environment variables. Use this for non-secret configuration values. | 41 | | config.envValueFrom | object | `{}` | Set environment variables from configMaps or Secrets | 42 | | config.existingSecret | string | `""` | Set this to the name of a secret to load environment variables from. If defined, values in the secret will override values in config.env | 43 | | config.files | list | `[{"content":"This is a test file with some content\n","mountPath":"/var/www/html/storage/configurations","name":"test.txt"}]` | A list of files with a mountPath, a file name and the file's content. Files are stored as a secret. | 44 | | fireflyiii.auth.accessToken | string | `""` | The access token in plain text | 45 | | fireflyiii.auth.existingSecret | string | `""` | If you specify an existingSecret, it has to have the accessToken in a .spec.data.accessToken | 46 | | fireflyiii.url | string | `"http://firefly-firefly-iii:80"` | The URL at which Firefly III is available. If you change this value, click the "Reauthenticate" button on the importer after opening it! | 47 | | fireflyiii.vanityUrl | string | `""` | The URL at which you access Firefly III. Check https://docs.firefly-iii.org/data-importer/install/configure/#configure-fidi to find out if you should set this. | 48 | | fullnameOverride | string | `""` | | 49 | | image.pullPolicy | string | `"IfNotPresent"` | | 50 | | image.repository | string | `"fireflyiii/data-importer"` | | 51 | | image.tag | string | `"version-1.9.1"` | | 52 | | imagePullSecrets | list | `[]` | | 53 | | ingress.annotations | object | `{}` | | 54 | | ingress.className | string | `""` | | 55 | | ingress.enabled | bool | `false` | | 56 | | ingress.hosts[0] | string | `"chart-example.local"` | | 57 | | ingress.tls | list | `[]` | | 58 | | nameOverride | string | `""` | | 59 | | nodeSelector | object | `{}` | | 60 | | podAnnotations | object | `{}` | | 61 | | podSecurityContext | object | `{}` | | 62 | | replicaCount | int | `1` | | 63 | | resources | object | `{}` | | 64 | | securityContext | object | `{}` | | 65 | | service.port | int | `80` | | 66 | | service.type | string | `"ClusterIP"` | | 67 | | tolerations | list | `[]` | | 68 | | trustedProxies | string | `"**"` | The proxies that are trusted by the importer | 69 | -------------------------------------------------------------------------------- /charts/firefly-iii/templates/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: {{ include "firefly-iii.fullname" . }} 5 | labels: 6 | {{- include "firefly-iii.labels" . | nindent 4 }} 7 | spec: 8 | {{- if not .Values.autoscaling.enabled }} 9 | replicas: {{ .Values.replicaCount }} 10 | {{- end }} 11 | strategy: 12 | type: {{ default "RollingUpdate" .Values.deploymentStrategyType }} 13 | selector: 14 | matchLabels: 15 | {{- include "firefly-iii.selectorLabels" . | nindent 6 }} 16 | template: 17 | metadata: 18 | annotations: 19 | checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} 20 | checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }} 21 | {{- with .Values.podAnnotations }} 22 | {{- toYaml . | nindent 8 }} 23 | {{- end }} 24 | labels: 25 | {{- include "firefly-iii.selectorLabels" . | nindent 8 }} 26 | spec: 27 | {{- with .Values.imagePullSecrets }} 28 | imagePullSecrets: 29 | {{- toYaml . | nindent 8 }} 30 | {{- end }} 31 | {{- with .Values.podSecurityContext }} 32 | securityContext: 33 | {{- toYaml . | nindent 8 }} 34 | {{- end }} 35 | containers: 36 | - name: {{ .Chart.Name }} 37 | {{- with .Values.securityContext }} 38 | securityContext: 39 | {{- toYaml . | nindent 12 }} 40 | {{- end }} 41 | {{- with .Values.image }} 42 | image: "{{ coalesce $.Values.global.image.registry .registry }}/{{ .repository }}:{{ .tag | default (printf "version-%s" $.Chart.AppVersion) }}" 43 | imagePullPolicy: {{ coalesce $.Values.global.image.pullPolicy .pullPolicy }} 44 | {{- end }} 45 | {{- if or .Values.config.envValueFrom }} 46 | env: 47 | {{- range $key, $value := .Values.config.envValueFrom }} 48 | - name: {{ $key }} 49 | valueFrom: {{- $value | toYaml | nindent 16 }} 50 | {{- end }} 51 | {{- end }} 52 | {{- if or (.Values.config.env) (.Values.config.existingSecret) }} 53 | envFrom: 54 | - secretRef: 55 | name: {{ template "firefly-iii.fullname" . }}-app-key 56 | {{- if .Values.config.env }} 57 | - configMapRef: 58 | name: {{ template "firefly-iii.fullname" . }} 59 | {{- end }} 60 | {{- if .Values.config.existingSecret }} 61 | - secretRef: 62 | name: {{ .Values.config.existingSecret }} 63 | {{- else if .Values.secrets.env }} 64 | - secretRef: 65 | name: {{ template "firefly-iii.fullname" . }} 66 | {{- end }} 67 | {{- end }} 68 | {{- if or (.Values.persistence.enabled) (.Values.extraVolumeMounts) }} 69 | volumeMounts: 70 | {{- with .Values.extraVolumeMounts }} 71 | {{- toYaml . | nindent 10 }} 72 | {{- end }} 73 | {{- if .Values.persistence.enabled }} 74 | - name: upload 75 | mountPath: "/var/www/html/storage/upload" 76 | {{- end }} 77 | {{- end }} 78 | ports: 79 | - name: http 80 | containerPort: 8080 81 | protocol: TCP 82 | livenessProbe: 83 | {{- with .Values.livenessProbe }} 84 | {{- toYaml . | nindent 10 }} 85 | {{- end }} 86 | readinessProbe: 87 | {{- with .Values.readinessProbe }} 88 | {{- toYaml . | nindent 10 }} 89 | {{- end }} 90 | startupProbe: 91 | {{- with .Values.startupProbe }} 92 | {{- toYaml . | nindent 10 }} 93 | {{- end }} 94 | 95 | {{- with .Values.resources }} 96 | resources: 97 | {{- toYaml . | nindent 12 }} 98 | {{- end }} 99 | {{- if or (.Values.persistence.enabled) (.Values.extraVolumes) }} 100 | volumes: 101 | {{- with .Values.extraVolumes }} 102 | {{- toYaml . | nindent 8 }} 103 | {{- end }} 104 | {{- if (.Values.persistence.enabled) }} 105 | - name: upload 106 | persistentVolumeClaim: 107 | claimName: {{ default (include "firefly-iii.fullname" .) .Values.persistence.existingClaim }} 108 | {{- end }} 109 | {{- end }} 110 | {{- with .Values.nodeSelector }} 111 | nodeSelector: 112 | {{- toYaml . | nindent 8 }} 113 | {{- end }} 114 | {{- with .Values.affinity }} 115 | affinity: 116 | {{- toYaml . | nindent 8 }} 117 | {{- end }} 118 | {{- with .Values.tolerations }} 119 | tolerations: 120 | {{- toYaml . | nindent 8 }} 121 | {{- end }} 122 | -------------------------------------------------------------------------------- /charts/firefly-iii-stack/README.md: -------------------------------------------------------------------------------- 1 | # firefly-iii-stack 2 | 3 | ![Version: 0.9.1](https://img.shields.io/badge/Version-0.9.1-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) 4 | 5 | Installs Firefly III stack (db, app, importer) 6 | **Homepage:** 7 | ## Maintainers 8 | 9 | | Name | Email | Url | 10 | | ---- | ------ | --- | 11 | | morremeyer | | | 12 | ## Source Code 13 | 14 | * 15 | ## Requirements 16 | 17 | | Repository | Name | Version | 18 | |------------|------|---------| 19 | | file://../firefly-db | firefly-db | 0.2.9 | 20 | | file://../firefly-iii | firefly-iii | 1.9.12 | 21 | | file://../importer | importer | 1.5.1 | 22 | 23 | ## Upgrading 24 | 25 | When a release introduces breaking changes, this section outlines the manual actions that need to be taken. 26 | 27 | ### From 0.4.0 to 0.5.0 28 | 29 | No breaking changes in this release, but you can now use the helm repository directly from https://firefly-iii.github.io/kubernetes/. 30 | 31 | ### From 0.1.0 to 0.2.0 32 | 33 | The **firefely** wrapper chart has been renamed to **firefly-iii-stack**. All charts are now contained directly in the `charts` directory, following best practices for chart repositories. 34 | 35 | ### From 0.0.5 to 0.1.0 36 | 37 | The `firefly-iii` chart has been overhauled and contains breaking changes. Please check out [the charts upgrade notes](charts/firefly-iii/README.md#from-004-to-100). 38 | 39 | ### From 0.0.4 to 0.0.5 40 | 41 | The `firefly-csv` chart has been removed as the CSV importer has been integrated into the importer. Please check out the new [`importer` chart](charts/importer/README.md). 42 | 43 | ### From 0.0.3 to 0.0.4 44 | 45 | The storage class and access modes have been changed to match more setups without the need for configuration. If you want to keep the old settings, set the following values: 46 | 47 | ```yaml 48 | firefly-iii: 49 | storage: 50 | class: nfs-client 51 | accessModes: ReadWriteMany 52 | 53 | firefly-csv: 54 | storage: 55 | class: nfs-client 56 | accessModes: ReadWriteMany 57 | 58 | firefly-db: 59 | storage: 60 | class: nfs-client 61 | accessModes: ReadWriteMany 62 | ``` 63 | 64 | ### From 0.0.2 to 0.0.3 65 | 66 | The `firefly-iii` and `firefly-csv` charts have been updated and now support configuring ingress annotations. 67 | 68 | To keep the old annotations, add the following values: 69 | 70 | ```yaml 71 | firefly-iii: 72 | ingress: 73 | annotations: 74 | kubernetes.io/ingress.class: "nginx" 75 | nginx.ingress.kubernetes.io/proxy-buffer-size: "16k" 76 | 77 | firefly-csv: 78 | ingress: 79 | annotations: 80 | kubernetes.io/ingress.class: "nginx" 81 | nginx.org/client-max-body-size: "0" 82 | nginx.ingress.kubernetes.io/proxy-buffer-size: "16k" 83 | ``` 84 | 85 | ## Development and testing 86 | 87 | ### Dependency chart overrides 88 | 89 | Unfortunately, helm does not yet have a neat mechanism to dynamically override chart dependencies for local development/testing. 90 | 91 | Therefore, you'll need to override the dependencies manually for local testing and development. To do so, you need to update the `Chart.yaml` file. 92 | 93 | For every dependency, replace `repository: https://firefly-iii.github.io/kubernetes/` with `repository: file://../${dependency_chart_name}`. 94 | 95 | ## Values 96 | 97 | | Key | Type | Default | Description | 98 | |-----|------|---------|-------------| 99 | | firefly-db.backupSchedule | string | `"0 3 * * *"` | | 100 | | firefly-db.configs.BACKUP_URL | string | `""` | | 101 | | firefly-db.configs.DBHOST | string | `""` | | 102 | | firefly-db.configs.DBNAME | string | `"firefly"` | | 103 | | firefly-db.configs.DBPORT | string | `"5432"` | | 104 | | firefly-db.configs.DBUSER | string | `"firefly"` | | 105 | | firefly-db.configs.PGPASSWORD | string | `""` | | 106 | | firefly-db.configs.RESTORE_URL | string | `""` | | 107 | | firefly-db.configs.TZ | string | `"Europe/Berlin"` | | 108 | | firefly-db.enabled | bool | `true` | | 109 | | firefly-db.image.pullPolicy | string | `"IfNotPresent"` | | 110 | | firefly-db.image.repository | string | `"postgres"` | | 111 | | firefly-db.image.tag | string | `"10-alpine"` | | 112 | | firefly-db.storage.accessModes | string | `nil` | | 113 | | firefly-db.storage.class | string | `nil` | | 114 | | firefly-db.storage.dataSize | string | `"1Gi"` | | 115 | | firefly-iii.config.env.DB_HOST | string | `""` | | 116 | | firefly-iii.config.env.DEFAULT_LANGUAGE | string | `"en_US"` | | 117 | | firefly-iii.config.env.DEFAULT_LOCALE | string | `"equal"` | | 118 | | firefly-iii.config.env.TRUSTED_PROXIES | string | `"**"` | | 119 | | firefly-iii.config.env.TZ | string | `"Europe/Amsterdam"` | | 120 | | firefly-iii.enabled | bool | `true` | Set to false to not deploy Firefly III | 121 | | importer.enabled | bool | `true` | Set to false to not deploy the importer | 122 | -------------------------------------------------------------------------------- /.devcontainer/Dockerfile: -------------------------------------------------------------------------------- 1 | # [Choice] Python version: 3, 3.8, 3.7, 3.6 2 | ARG VARIANT=3 3 | FROM mcr.microsoft.com/vscode/devcontainers/python:${VARIANT} 4 | 5 | # Options 6 | ARG INSTALL_NODE="true" 7 | ARG NODE_VERSION="lts/*" 8 | ARG ENABLE_NONROOT_DOCKER="true" 9 | ARG SOURCE_SOCKET=/var/run/docker-host.sock 10 | ARG TARGET_SOCKET=/var/run/docker.sock 11 | ARG USERNAME=vscode 12 | ARG USER_UID=1000 13 | ARG USER_GID=$USER_UID 14 | 15 | # Install needed packages and setup non-root user. Use a separate RUN statement to add your own dependencies. 16 | COPY library-scripts/*.sh /tmp/library-scripts/ 17 | RUN apt-get update \ 18 | # Use Docker script from script library to set things up 19 | && /bin/bash /tmp/library-scripts/docker-debian.sh "${ENABLE_NONROOT_DOCKER}" "${SOURCE_SOCKET}" "${TARGET_SOCKET}" "${USERNAME}" \ 20 | # Clean up 21 | && apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/lists/* /tmp/library-scripts/ 22 | # Install kubectl 23 | RUN curl -sSL -o /usr/local/bin/kubectl https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl \ 24 | && chmod +x /usr/local/bin/kubectl 25 | 26 | # Install Helm 27 | RUN curl -s https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash - 28 | 29 | # Script copies localhost's ~/.kube/config file into the container and swaps out 30 | # localhost for host.docker.internal on bash/zsh start to keep them in sync. 31 | COPY library-scripts/copy-kube-config.sh /usr/local/share/ 32 | RUN chown ${USERNAME}:root /usr/local/share/copy-kube-config.sh \ 33 | && echo "source /usr/local/share/copy-kube-config.sh" | tee -a /root/.bashrc /root/.zshrc /home/${USERNAME}/.bashrc >> /home/${USERNAME}/.zshrc 34 | 35 | ### end of base Dockerfile ### 36 | 37 | # Setting the ENTRYPOINT to docker-init.sh will configure non-root access to 38 | # the Docker socket if "overrideCommand": false is set in devcontainer.json. 39 | # The script will also execute CMD if you need to alter startup behaviors. 40 | ENTRYPOINT [ "/usr/local/share/docker-init.sh" ] 41 | CMD [ "sleep", "infinity" ] 42 | 43 | # [Optional] Install Node.js 44 | RUN if [ "${INSTALL_NODE}" = "true" ]; then su ${USERNAME} -c "source /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"; fi 45 | 46 | RUN export DEBIAN_FRONTEND=noninteractive \ 47 | # add build-essential and golang 48 | # 49 | && apt-get update && apt-get install -y build-essential golang \ 50 | # 51 | # add arkade https://github.com/alexellis/arkade 52 | # 53 | && curl -sLS https://dl.get-arkade.dev | sudo sh \ 54 | # Add the HashiCorp GPG key and add the official HashiCorp Linux repository 55 | && apt-get update && apt-get install -y software-properties-common \ 56 | && curl -fsSL https://apt.releases.hashicorp.com/gpg | apt-key add - \ 57 | && apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main" \ 58 | # 59 | # Download and register the Microsoft repository GPG keys 60 | && wget https://packages.microsoft.com/config/debian/10/packages-microsoft-prod.deb \ 61 | && dpkg -i packages-microsoft-prod.deb \ 62 | && rm packages-microsoft-prod.deb \ 63 | # 64 | # update apt package cache 65 | && apt-get update \ 66 | # 67 | # Install helm/kubectl bash/zsh completion 68 | && echo 'source <(kubectl completion bash)' | tee -a /root/.bashrc /home/${USERNAME}/.bashrc \ 69 | && echo 'source <(helm completion bash)' | tee -a /root/.bashrc /home/${USERNAME}/.bashrc \ 70 | && echo 'source <(kubectl completion zsh)' | tee -a /root/.zshrc /home/${USERNAME}/.zshrc \ 71 | && echo 'source <(helm completion zsh)' | tee -a /root/.zshrc /home/${USERNAME}/.zshrc \ 72 | # 73 | # Install Ansible with bash completion 74 | && apt-get install -y python3-argcomplete \ 75 | && pip3 install ansible pyvmomi pywinrm[credssp] pywinrm[kerberos] \ 76 | && activate-global-python-argcomplete3 \ 77 | # 78 | # Install govc (vSphere CLI) 79 | && curl -LO https://github.com/vmware/govmomi/releases/download/v0.24.0/govc_linux_amd64.gz \ 80 | && gzip -d govc_linux_amd64.gz \ 81 | && install govc_linux_amd64 /usr/local/bin/govc \ 82 | && rm govc_linux_amd64 \ 83 | # 84 | # Install HashiCorp Terraform, Packer and Vault with completion for root and non-root usage 85 | && apt-get install -y terraform packer vault \ 86 | && terraform -install-autocomplete \ 87 | && su ${USERNAME} -c "terraform -install-autocomplete" \ 88 | && packer -autocomplete-install -machine-readable \ 89 | && su ${USERNAME} -c "packer -autocomplete-install -machine-readable" \ 90 | # disable IPC_LOCK to configure completion during build 91 | && setcap cap_ipc_lock=-ep $(readlink -f $(which vault)) \ 92 | && vault -autocomplete-install \ 93 | && su ${USERNAME} -c "vault -autocomplete-install" \ 94 | # re-enable IPC_LOCK 95 | && setcap cap_ipc_lock=+ep $(readlink -f $(which vault)) \ 96 | # 97 | # install PowerShell 98 | && apt-get install -y powershell \ 99 | # 100 | # Clean up 101 | && apt-get autoremove -y \ 102 | && apt-get clean -y \ 103 | && rm -rf /var/lib/apt/lists/* 104 | 105 | # copy govc completion file into container 106 | COPY library-scripts/govc-completion.sh /etc/bash_completion.d/ 107 | RUN echo 'source /etc/bash_completion.d/govc-completion.sh' | tee -a /root/.zshrc /home/${USERNAME}/.zshrc -------------------------------------------------------------------------------- /charts/firefly-iii/values.yaml: -------------------------------------------------------------------------------- 1 | global: 2 | image: 3 | # -- if set it will overwrite all registry entries 4 | registry: 5 | # -- if set it will overwrite all pullPolicy 6 | pullPolicy: 7 | 8 | replicaCount: 1 9 | deploymentStrategyType: RollingUpdate 10 | 11 | image: 12 | registry: "docker.io" 13 | repository: "fireflyiii/core" 14 | pullPolicy: IfNotPresent 15 | # -- Overrides the image tag whose default is the chart appVersion. 16 | tag: "" 17 | 18 | imagePullSecrets: [] 19 | nameOverride: "" 20 | fullnameOverride: "" 21 | 22 | persistence: 23 | # -- If you set this to false, uploaded attachments are not stored persistently and will be lost with every restart of the pod 24 | enabled: true 25 | storageClassName: "" 26 | accessModes: ReadWriteOnce 27 | # volumeName: your-pv-name 28 | # selector: 29 | # matchLabels: 30 | # app: my-app 31 | storage: 1Gi 32 | # -- If you want to use an existing claim, set it here 33 | existingClaim: "" 34 | 35 | # -- Environment variables for Firefly III. See docs at: https://github.com/firefly-iii/firefly-iii/blob/main/.env.example 36 | config: 37 | # -- Set this to the name of a secret to load environment variables from. If defined, values in the secret will override values in config.env 38 | existingSecret: "" 39 | 40 | # -- Set environment variables from configMaps or Secrets 41 | envValueFrom: {} 42 | 43 | # -- Directly defined environment variables. Use this for non-secret configuration values. 44 | env: 45 | DB_HOST: 46 | DB_CONNECTION: pgsql 47 | DB_PORT: "5432" 48 | DB_DATABASE: firefly 49 | DB_USERNAME: firefly 50 | DEFAULT_LANGUAGE: "en_US" 51 | DEFAULT_LOCALE: "equal" 52 | TZ: "Europe/Amsterdam" 53 | TRUSTED_PROXIES: "**" 54 | 55 | # -- Create a new Secret from values file to store sensitive environment variables. Make sure to keep your secrets encrypted in the repository! For example, you can use the 'helm secrets' plugin (https://github.com/jkroepke/helm-secrets) to encrypt and manage secrets. If the 'config.existingSecret' value is set, a new Secret will not be created. 56 | secrets: 57 | env: 58 | APP_PASSWORD: "CHANGE_ENCRYPT_ME" 59 | DB_PASSWORD: "CHANGE_ENCRYPT_ME" 60 | # -- Statically set the APP_KEY in case this is desired over the autogeneration. Should be a random 32-character string. 61 | # -- Can be generated using: `cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1` 62 | # appKey: "CHANGE_ME" 63 | 64 | # -- A cronjob for [recurring Firefly III tasks](https://docs.firefly-iii.org/firefly-iii/advanced-installation/cron/). 65 | cronjob: 66 | # -- Set to true to enable the CronJob. Note that you need to specify either cronjob.auth.existingSecret or cronjob.auth.token for it to actually be deployed. 67 | enabled: false 68 | 69 | # -- Authorization for the CronJob. See https://docs.firefly-iii.org/firefly-iii/advanced-installation/cron/#request-a-page-over-the-web 70 | auth: 71 | # -- The name of a secret containing a data.token field with the cronjob token 72 | existingSecret: "" 73 | 74 | # -- The name of the key in the existing secret to get the cronjob token from 75 | secretKey: "token" 76 | 77 | # -- The token in plain text 78 | token: "" 79 | 80 | # -- Annotations for the CronJob 81 | annotations: {} 82 | 83 | # -- When to run the CronJob. Defaults to 03:00 as this is when Firefly III executes regular tasks. 84 | schedule: "0 3 * * *" 85 | 86 | # -- How many pods to keep around for successful jobs 87 | successfulJobsHistoryLimit: 3 88 | 89 | # -- How many pods to keep around for failed jobs 90 | failedJobsHistoryLimit: 1 91 | 92 | # -- How to treat failed jobs 93 | restartPolicy: OnFailure 94 | 95 | image: 96 | registry: docker.io 97 | repository: curlimages/curl 98 | pullPolicy: IfNotPresent 99 | tag: 8.12.0 100 | 101 | imagePullSecrets: [] 102 | 103 | podAnnotations: {} 104 | 105 | securityContext: {} 106 | 107 | podSecurityContext: {} 108 | 109 | resources: {} 110 | 111 | nodeSelector: {} 112 | 113 | tolerations: [] 114 | 115 | affinity: {} 116 | 117 | podAnnotations: {} 118 | 119 | podSecurityContext: {} 120 | # fsGroup: 2000 121 | 122 | securityContext: {} 123 | # capabilities: 124 | # drop: 125 | # - ALL 126 | # readOnlyRootFilesystem: true 127 | # runAsNonRoot: true 128 | # runAsUser: 1000 129 | 130 | service: 131 | type: ClusterIP 132 | port: 80 133 | 134 | ingress: 135 | enabled: false 136 | className: "" 137 | annotations: {} 138 | # kubernetes.io/ingress.class: nginx 139 | # kubernetes.io/tls-acme: "true" 140 | hosts: 141 | - chart-example.local 142 | tls: [] 143 | # - secretName: chart-example-tls 144 | # hosts: 145 | # - chart-example.local 146 | 147 | resources: {} 148 | # We usually recommend not to specify default resources and to leave this as a conscious 149 | # choice for the user. This also increases chances charts run on environments with little 150 | # resources, such as Minikube. If you do want to specify resources, uncomment the following 151 | # lines, adjust them as necessary, and remove the curly braces after 'resources:'. 152 | # limits: 153 | # cpu: 100m 154 | # memory: 128Mi 155 | # requests: 156 | # cpu: 100m 157 | # memory: 128Mi 158 | 159 | autoscaling: 160 | enabled: false 161 | minReplicas: 1 162 | maxReplicas: 100 163 | targetCPUUtilizationPercentage: 80 164 | # targetMemoryUtilizationPercentage: 80 165 | 166 | nodeSelector: {} 167 | 168 | tolerations: [] 169 | 170 | affinity: {} 171 | 172 | # Here, you can specify custom volumes to use. 173 | extraVolumes: [] 174 | # - name: db-tls-firefly 175 | # secret: 176 | # secretName: db-tls-firefly 177 | # defaultMode: 0440 178 | 179 | # And here, your custom volume mounts. 180 | extraVolumeMounts: [] 181 | # - name: db-tls-firefly 182 | # mountPath: /db-cert 183 | # readOnly: true 184 | 185 | livenessProbe: 186 | httpGet: 187 | path: /health 188 | port: http 189 | readinessProbe: 190 | httpGet: 191 | path: /health 192 | port: http 193 | initialDelaySeconds: 15 194 | timeoutSeconds: 1 195 | startupProbe: 196 | httpGet: 197 | path: /health 198 | port: http 199 | # Give the app 30 x 10 = 300s to startup 200 | failureThreshold: 30 201 | periodSeconds: 10 202 | -------------------------------------------------------------------------------- /.devcontainer/library-scripts/docker-debian.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | #------------------------------------------------------------------------------------------------------------- 3 | # Copyright (c) Microsoft Corporation. All rights reserved. 4 | # Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information. 5 | #------------------------------------------------------------------------------------------------------------- 6 | # 7 | # Docs: https://github.com/microsoft/vscode-dev-containers/blob/master/script-library/docs/docker.md 8 | # Maintainer: The VS Code and Codespaces Teams 9 | # 10 | # Syntax: ./docker-debian.sh [enable non-root docker socket access flag] [source socket] [target socket] [non-root user] [use moby] 11 | 12 | ENABLE_NONROOT_DOCKER=${1:-"true"} 13 | SOURCE_SOCKET=${2:-"/var/run/docker-host.sock"} 14 | TARGET_SOCKET=${3:-"/var/run/docker.sock"} 15 | USERNAME=${4:-"automatic"} 16 | USE_MOBY=${5:-"true"} 17 | 18 | set -e 19 | 20 | if [ "$(id -u)" -ne 0 ]; then 21 | echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.' 22 | exit 1 23 | fi 24 | 25 | # Determine the appropriate non-root user 26 | if [ "${USERNAME}" = "auto" ] || [ "${USERNAME}" = "automatic" ]; then 27 | USERNAME="" 28 | POSSIBLE_USERS=("vscode" "node" "codespace" "$(awk -v val=1000 -F ":" '$3==val{print $1}' /etc/passwd)") 29 | for CURRENT_USER in ${POSSIBLE_USERS[@]}; do 30 | if id -u ${CURRENT_USER} > /dev/null 2>&1; then 31 | USERNAME=${CURRENT_USER} 32 | break 33 | fi 34 | done 35 | if [ "${USERNAME}" = "" ]; then 36 | USERNAME=root 37 | fi 38 | elif [ "${USERNAME}" = "none" ] || ! id -u ${USERNAME} > /dev/null 2>&1; then 39 | USERNAME=root 40 | fi 41 | 42 | # Function to run apt-get if needed 43 | apt-get-update-if-needed() 44 | { 45 | if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then 46 | echo "Running apt-get update..." 47 | apt-get update 48 | else 49 | echo "Skipping apt-get update." 50 | fi 51 | } 52 | 53 | # Ensure apt is in non-interactive to avoid prompts 54 | export DEBIAN_FRONTEND=noninteractive 55 | 56 | # Install apt-transport-https, curl, lsb-release, gpg if missing 57 | if ! dpkg -s apt-transport-https curl ca-certificates lsb-release > /dev/null 2>&1 || ! type gpg > /dev/null 2>&1; then 58 | apt-get-update-if-needed 59 | apt-get -y install --no-install-recommends apt-transport-https curl ca-certificates lsb-release gnupg2 60 | fi 61 | 62 | # Install Docker / Moby CLI if not already installed 63 | if type docker > /dev/null 2>&1; then 64 | echo "Docker / Moby CLI already installed." 65 | else 66 | if [ "${USE_MOBY}" = "true" ]; then 67 | DISTRO=$(lsb_release -is | tr '[:upper:]' '[:lower:]') 68 | CODENAME=$(lsb_release -cs) 69 | curl -s https://packages.microsoft.com/keys/microsoft.asc | (OUT=$(apt-key add - 2>&1) || echo $OUT) 70 | echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-${DISTRO}-${CODENAME}-prod ${CODENAME} main" > /etc/apt/sources.list.d/microsoft.list 71 | apt-get update 72 | apt-get -y install --no-install-recommends moby-cli 73 | else 74 | curl -fsSL https://download.docker.com/linux/$(lsb_release -is | tr '[:upper:]' '[:lower:]')/gpg | (OUT=$(apt-key add - 2>&1) || echo $OUT) 75 | echo "deb [arch=amd64] https://download.docker.com/linux/$(lsb_release -is | tr '[:upper:]' '[:lower:]') $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list 76 | apt-get update 77 | apt-get -y install --no-install-recommends docker-ce-cli 78 | fi 79 | fi 80 | 81 | # Install Docker Compose if not already installed 82 | if type docker-compose > /dev/null 2>&1; then 83 | echo "Docker Compose already installed." 84 | else 85 | LATEST_COMPOSE_VERSION=$(curl -sSL "https://api.github.com/repos/docker/compose/releases/latest" | grep -o -P '(?<="tag_name": ").+(?=")') 86 | curl -sSL "https://github.com/docker/compose/releases/download/${LATEST_COMPOSE_VERSION}/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose 87 | chmod +x /usr/local/bin/docker-compose 88 | fi 89 | 90 | # If init file already exists, exit 91 | if [ -f "/usr/local/share/docker-init.sh" ]; then 92 | exit 0 93 | fi 94 | 95 | # By default, make the source and target sockets the same 96 | if [ "${SOURCE_SOCKET}" != "${TARGET_SOCKET}" ]; then 97 | touch "${SOURCE_SOCKET}" 98 | ln -s "${SOURCE_SOCKET}" "${TARGET_SOCKET}" 99 | fi 100 | 101 | # Add a stub if not adding non-root user access, user is root 102 | if [ "${ENABLE_NONROOT_DOCKER}" = "false" ] || [ "${USERNAME}" = "root" ]; then 103 | echo '/usr/bin/env bash -c "\$@"' > /usr/local/share/docker-init.sh 104 | chmod +x /usr/local/share/docker-init.sh 105 | exit 0 106 | fi 107 | 108 | # If enabling non-root access and specified user is found, setup socat and add script 109 | chown -h "${USERNAME}":root "${TARGET_SOCKET}" 110 | if ! dpkg -s socat > /dev/null 2>&1; then 111 | apt-get-update-if-needed 112 | apt-get -y install socat 113 | fi 114 | tee /usr/local/share/docker-init.sh > /dev/null \ 115 | << EOF 116 | #!/usr/bin/env bash 117 | #------------------------------------------------------------------------------------------------------------- 118 | # Copyright (c) Microsoft Corporation. All rights reserved. 119 | # Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information. 120 | #------------------------------------------------------------------------------------------------------------- 121 | set -e 122 | SOCAT_PATH_BASE=/tmp/vscr-docker-from-docker 123 | SOCAT_LOG=\${SOCAT_PATH_BASE}.log 124 | SOCAT_PID=\${SOCAT_PATH_BASE}.pid 125 | # Wrapper function to only use sudo if not already root 126 | sudoIf() 127 | { 128 | if [ "\$(id -u)" -ne 0 ]; then 129 | sudo "\$@" 130 | else 131 | "\$@" 132 | fi 133 | } 134 | # Log messages 135 | log() 136 | { 137 | echo -e "[\$(date)] \$@" | sudoIf tee -a \${SOCAT_LOG} > /dev/null 138 | } 139 | echo -e "\n** \$(date) **" | sudoIf tee -a \${SOCAT_LOG} > /dev/null 140 | log "Ensuring ${USERNAME} has access to ${SOURCE_SOCKET} via ${TARGET_SOCKET}" 141 | # If enabled, try to add a docker group with the right GID. If the group is root, 142 | # fall back on using socat to forward the docker socket to another unix socket so 143 | # that we can set permissions on it without affecting the host. 144 | if [ "${ENABLE_NONROOT_DOCKER}" = "true" ] && [ "${SOURCE_SOCKET}" != "${TARGET_SOCKET}" ] && [ "${USERNAME}" != "root" ] && [ "${USERNAME}" != "0" ]; then 145 | SOCKET_GID=\$(stat -c '%g' ${SOURCE_SOCKET}) 146 | if [ "\${SOCKET_GID}" != "0" ]; then 147 | log "Adding user to group with GID \${SOCKET_GID}." 148 | if [ "\$(cat /etc/group | grep :\${SOCKET_GID}:)" = "" ]; then 149 | sudoIf groupadd --gid \${SOCKET_GID} docker-host 150 | fi 151 | # Add user to group if not already in it 152 | if [ "\$(id ${USERNAME} | grep -E "groups.*(=|,)\${SOCKET_GID}\(")" = "" ]; then 153 | sudoIf usermod -aG \${SOCKET_GID} ${USERNAME} 154 | fi 155 | else 156 | # Enable proxy if not already running 157 | if [ ! -f "\${SOCAT_PID}" ] || ! ps -p \$(cat \${SOCAT_PID}) > /dev/null; then 158 | log "Enabling socket proxy." 159 | log "Proxying ${SOURCE_SOCKET} to ${TARGET_SOCKET} for vscode" 160 | sudoIf rm -rf ${TARGET_SOCKET} 161 | (sudoIf socat UNIX-LISTEN:${TARGET_SOCKET},fork,mode=660,user=${USERNAME} UNIX-CONNECT:${SOURCE_SOCKET} 2>&1 | sudoIf tee -a \${SOCAT_LOG} > /dev/null & echo "\$!" | sudoIf tee \${SOCAT_PID} > /dev/null) 162 | else 163 | log "Socket proxy already running." 164 | fi 165 | fi 166 | log "Success" 167 | fi 168 | # Execute whatever commands were passed in (if any). This allows us 169 | # to set this script to ENTRYPOINT while still executing the default CMD. 170 | set +e 171 | exec "\$@" 172 | EOF 173 | chmod +x /usr/local/share/docker-init.sh 174 | chown ${USERNAME}:root /usr/local/share/docker-init.sh 175 | echo "Done!" -------------------------------------------------------------------------------- /charts/firefly-iii/README.md: -------------------------------------------------------------------------------- 1 | # firefly-iii 2 | 3 | ![Version: 1.9.12](https://img.shields.io/badge/Version-1.9.12-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 6.4.9](https://img.shields.io/badge/AppVersion-6.4.9-informational?style=flat-square) 4 | 5 | Installs Firefly III 6 | **Homepage:** 7 | ## Maintainers 8 | 9 | | Name | Email | Url | 10 | | ---- | ------ | --- | 11 | | morremeyer | | | 12 | ## Source Code 13 | 14 | * 15 | 16 | ## Setting environment variables from additional ConfigMaps and Secrets 17 | 18 | This enables a simplified syntax to set envirnoment variables from a ConfigMap or Secret: 19 | 20 | ```yaml 21 | envValueFrom: 22 | USER: 23 | secretKeyRef: 24 | name: secret-name 25 | key: user 26 | ``` 27 | 28 | ## Upgrading 29 | 30 | When a release introduces breaking changes, this section outlines the manual actions that need to be taken. 31 | 32 | ### From 0.0.4 to 1.0.0 33 | 34 | This version bump is a full rework of the chart to be in line with current helm best practices and to add configurability. See the subsections for all changes. 35 | 36 | A cronjob has been added to support [Firefly III features that need it](https://docs.firefly-iii.org/firefly-iii/advanced-installation/cron/). It is disabled by default, set `cronjob.enabled` to true to enable it. Please note that you need to specify `cronjob.auth.token` or `cronjob.auth.existingSecret` so that the job is actually deployed an can run. If you specify an existingSecret, it needs to have the token in the field `token`. 37 | 38 | #### Resources 39 | 40 | The PVC has been renamed. You therefore need to manually back up and restore the upload data or retain and reclaim the PV with the new PVC. As this is highly dependant on your Kubernetes distribution and provider, instructions for the latter can't be generalized. 41 | 42 | To backup and restore your files easily, use `kubectl cp $FIREFLY_POD_NAME:/var/www/html/storage/upload $LOCAL_BACKUP_DIR`, apply the changes and then reverse the process by running `kubectl cp "${LOCAL_BACKUP_DIR}/*" $FIREFLY_POD_NAME:/var/www/html/storage/upload/`. 43 | 44 | #### values.yaml 45 | 46 | The configuration has changed as follows: 47 | 48 | * `storage` has been moved to `persistence`. There's a new `persistence.enabled` value that is `true` by default. 49 | * `storage.dataSize` has been moved to `persistence.storage`. 50 | * `hostName` has moved to a list in `ingress.hosts` 51 | * The ingress is disabled by default. Set `ingress.enabled` to `true` to enable it 52 | * `configs` has moved to `config.env` 53 | * A new key `config.existingSecret` has been added. It references a secret where you can store Firefly III configuration environment variables. Environment variables specified in the secret override the ones in `config.env`. 54 | 55 | #### Labels 56 | 57 | The pod label keys have changed as follows: 58 | 59 | * `app` has been replaced by `app.kubernetes.io/name` 60 | * `chart` has been replaced by `helm.sh/chart` 61 | * `release` has been replaced by `app.kubernetes.io/instance` 62 | * `heritage` has been replaced by `app.kubernetes.io/managed-by` 63 | 64 | ### From 0.0.3 to 0.0.4 65 | 66 | The storage class and access modes have been changed to match more setups without the need for configuration. If you want to keep the old settings, set the following values: 67 | 68 | ```yaml 69 | storage: 70 | class: nfs-client 71 | accessModes: ReadWriteMany 72 | ``` 73 | 74 | ### From 0.0.2 to 0.0.3 75 | 76 | The Ingress annotations have been made configurable. To keep the annotations set in 0.0.2, add the following to your values: 77 | 78 | ```yaml 79 | ingress: 80 | annotations: 81 | kubernetes.io/ingress.class: "nginx" 82 | nginx.ingress.kubernetes.io/proxy-buffer-size: "16k" 83 | ``` 84 | 85 | ## Values 86 | 87 | | Key | Type | Default | Description | 88 | |-----|------|---------|-------------| 89 | | affinity | object | `{}` | | 90 | | autoscaling.enabled | bool | `false` | | 91 | | autoscaling.maxReplicas | int | `100` | | 92 | | autoscaling.minReplicas | int | `1` | | 93 | | autoscaling.targetCPUUtilizationPercentage | int | `80` | | 94 | | config | object | `{"env":{"DB_CONNECTION":"pgsql","DB_DATABASE":"firefly","DB_HOST":null,"DB_PORT":"5432","DB_USERNAME":"firefly","DEFAULT_LANGUAGE":"en_US","DEFAULT_LOCALE":"equal","TRUSTED_PROXIES":"**","TZ":"Europe/Amsterdam"},"envValueFrom":{},"existingSecret":""}` | Environment variables for Firefly III. See docs at: https://github.com/firefly-iii/firefly-iii/blob/main/.env.example | 95 | | config.env | object | `{"DB_CONNECTION":"pgsql","DB_DATABASE":"firefly","DB_HOST":null,"DB_PORT":"5432","DB_USERNAME":"firefly","DEFAULT_LANGUAGE":"en_US","DEFAULT_LOCALE":"equal","TRUSTED_PROXIES":"**","TZ":"Europe/Amsterdam"}` | Directly defined environment variables. Use this for non-secret configuration values. | 96 | | config.envValueFrom | object | `{}` | Set environment variables from configMaps or Secrets | 97 | | config.existingSecret | string | `""` | Set this to the name of a secret to load environment variables from. If defined, values in the secret will override values in config.env | 98 | | cronjob | object | `{"affinity":{},"annotations":{},"auth":{"existingSecret":"","secretKey":"token","token":""},"enabled":false,"failedJobsHistoryLimit":1,"image":{"pullPolicy":"IfNotPresent","registry":"docker.io","repository":"curlimages/curl","tag":"8.12.0"},"imagePullSecrets":[],"nodeSelector":{},"podAnnotations":{},"podSecurityContext":{},"resources":{},"restartPolicy":"OnFailure","schedule":"0 3 * * *","securityContext":{},"successfulJobsHistoryLimit":3,"tolerations":[]}` | A cronjob for [recurring Firefly III tasks](https://docs.firefly-iii.org/firefly-iii/advanced-installation/cron/). | 99 | | cronjob.annotations | object | `{}` | Annotations for the CronJob | 100 | | cronjob.auth | object | `{"existingSecret":"","secretKey":"token","token":""}` | Authorization for the CronJob. See https://docs.firefly-iii.org/firefly-iii/advanced-installation/cron/#request-a-page-over-the-web | 101 | | cronjob.auth.existingSecret | string | `""` | The name of a secret containing a data.token field with the cronjob token | 102 | | cronjob.auth.secretKey | string | `"token"` | The name of the key in the existing secret to get the cronjob token from | 103 | | cronjob.auth.token | string | `""` | The token in plain text | 104 | | cronjob.enabled | bool | `false` | Set to true to enable the CronJob. Note that you need to specify either cronjob.auth.existingSecret or cronjob.auth.token for it to actually be deployed. | 105 | | cronjob.failedJobsHistoryLimit | int | `1` | How many pods to keep around for failed jobs | 106 | | cronjob.restartPolicy | string | `"OnFailure"` | How to treat failed jobs | 107 | | cronjob.schedule | string | `"0 3 * * *"` | When to run the CronJob. Defaults to 03:00 as this is when Firefly III executes regular tasks. | 108 | | cronjob.successfulJobsHistoryLimit | int | `3` | How many pods to keep around for successful jobs | 109 | | deploymentStrategyType | string | `"RollingUpdate"` | | 110 | | extraVolumeMounts | list | `[]` | | 111 | | extraVolumes | list | `[]` | | 112 | | fullnameOverride | string | `""` | | 113 | | global.image.pullPolicy | string | `nil` | if set it will overwrite all pullPolicy | 114 | | global.image.registry | string | `nil` | if set it will overwrite all registry entries | 115 | | image.pullPolicy | string | `"IfNotPresent"` | | 116 | | image.registry | string | `"docker.io"` | | 117 | | image.repository | string | `"fireflyiii/core"` | | 118 | | image.tag | string | `""` | Overrides the image tag whose default is the chart appVersion. | 119 | | imagePullSecrets | list | `[]` | | 120 | | ingress.annotations | object | `{}` | | 121 | | ingress.className | string | `""` | | 122 | | ingress.enabled | bool | `false` | | 123 | | ingress.hosts[0] | string | `"chart-example.local"` | | 124 | | ingress.tls | list | `[]` | | 125 | | livenessProbe.httpGet.path | string | `"/health"` | | 126 | | livenessProbe.httpGet.port | string | `"http"` | | 127 | | nameOverride | string | `""` | | 128 | | nodeSelector | object | `{}` | | 129 | | persistence.accessModes | string | `"ReadWriteOnce"` | | 130 | | persistence.enabled | bool | `true` | If you set this to false, uploaded attachments are not stored persistently and will be lost with every restart of the pod | 131 | | persistence.existingClaim | string | `""` | If you want to use an existing claim, set it here | 132 | | persistence.storage | string | `"1Gi"` | | 133 | | persistence.storageClassName | string | `""` | | 134 | | podAnnotations | object | `{}` | | 135 | | podSecurityContext | object | `{}` | | 136 | | readinessProbe.httpGet.path | string | `"/health"` | | 137 | | readinessProbe.httpGet.port | string | `"http"` | | 138 | | readinessProbe.initialDelaySeconds | int | `15` | | 139 | | readinessProbe.timeoutSeconds | int | `1` | | 140 | | replicaCount | int | `1` | | 141 | | resources | object | `{}` | | 142 | | secrets | object | `{"env":{"APP_PASSWORD":"CHANGE_ENCRYPT_ME","DB_PASSWORD":"CHANGE_ENCRYPT_ME"}}` | Create a new Secret from values file to store sensitive environment variables. Make sure to keep your secrets encrypted in the repository! For example, you can use the 'helm secrets' plugin (https://github.com/jkroepke/helm-secrets) to encrypt and manage secrets. If the 'config.existingSecret' value is set, a new Secret will not be created. | 143 | | securityContext | object | `{}` | | 144 | | service.port | int | `80` | | 145 | | service.type | string | `"ClusterIP"` | | 146 | | startupProbe.failureThreshold | int | `30` | | 147 | | startupProbe.httpGet.path | string | `"/health"` | | 148 | | startupProbe.httpGet.port | string | `"http"` | | 149 | | startupProbe.periodSeconds | int | `10` | | 150 | | tolerations | list | `[]` | | 151 | -------------------------------------------------------------------------------- /license: -------------------------------------------------------------------------------- 1 | GNU AFFERO GENERAL PUBLIC LICENSE 2 | Version 3, 19 November 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU Affero General Public License is a free, copyleft license for 11 | software and other kinds of works, specifically designed to ensure 12 | cooperation with the community in the case of network server software. 13 | 14 | The licenses for most software and other practical works are designed 15 | to take away your freedom to share and change the works. By contrast, 16 | our General Public Licenses are intended to guarantee your freedom to 17 | share and change all versions of a program--to make sure it remains free 18 | software for all its users. 19 | 20 | When we speak of free software, we are referring to freedom, not 21 | price. Our General Public Licenses are designed to make sure that you 22 | have the freedom to distribute copies of free software (and charge for 23 | them if you wish), that you receive source code or can get it if you 24 | want it, that you can change the software or use pieces of it in new 25 | free programs, and that you know you can do these things. 26 | 27 | Developers that use our General Public Licenses protect your rights 28 | with two steps: (1) assert copyright on the software, and (2) offer 29 | you this License which gives you legal permission to copy, distribute 30 | and/or modify the software. 31 | 32 | A secondary benefit of defending all users' freedom is that 33 | improvements made in alternate versions of the program, if they 34 | receive widespread use, become available for other developers to 35 | incorporate. Many developers of free software are heartened and 36 | encouraged by the resulting cooperation. However, in the case of 37 | software used on network servers, this result may fail to come about. 38 | The GNU General Public License permits making a modified version and 39 | letting the public access it on a server without ever releasing its 40 | source code to the public. 41 | 42 | The GNU Affero General Public License is designed specifically to 43 | ensure that, in such cases, the modified source code becomes available 44 | to the community. It requires the operator of a network server to 45 | provide the source code of the modified version running there to the 46 | users of that server. Therefore, public use of a modified version, on 47 | a publicly accessible server, gives the public access to the source 48 | code of the modified version. 49 | 50 | An older license, called the Affero General Public License and 51 | published by Affero, was designed to accomplish similar goals. This is 52 | a different license, not a version of the Affero GPL, but Affero has 53 | released a new version of the Affero GPL which permits relicensing under 54 | this license. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | TERMS AND CONDITIONS 60 | 61 | 0. Definitions. 62 | 63 | "This License" refers to version 3 of the GNU Affero General Public License. 64 | 65 | "Copyright" also means copyright-like laws that apply to other kinds of 66 | works, such as semiconductor masks. 67 | 68 | "The Program" refers to any copyrightable work licensed under this 69 | License. Each licensee is addressed as "you". "Licensees" and 70 | "recipients" may be individuals or organizations. 71 | 72 | To "modify" a work means to copy from or adapt all or part of the work 73 | in a fashion requiring copyright permission, other than the making of an 74 | exact copy. The resulting work is called a "modified version" of the 75 | earlier work or a work "based on" the earlier work. 76 | 77 | A "covered work" means either the unmodified Program or a work based 78 | on the Program. 79 | 80 | To "propagate" a work means to do anything with it that, without 81 | permission, would make you directly or secondarily liable for 82 | infringement under applicable copyright law, except executing it on a 83 | computer or modifying a private copy. Propagation includes copying, 84 | distribution (with or without modification), making available to the 85 | public, and in some countries other activities as well. 86 | 87 | To "convey" a work means any kind of propagation that enables other 88 | parties to make or receive copies. Mere interaction with a user through 89 | a computer network, with no transfer of a copy, is not conveying. 90 | 91 | An interactive user interface displays "Appropriate Legal Notices" 92 | to the extent that it includes a convenient and prominently visible 93 | feature that (1) displays an appropriate copyright notice, and (2) 94 | tells the user that there is no warranty for the work (except to the 95 | extent that warranties are provided), that licensees may convey the 96 | work under this License, and how to view a copy of this License. If 97 | the interface presents a list of user commands or options, such as a 98 | menu, a prominent item in the list meets this criterion. 99 | 100 | 1. Source Code. 101 | 102 | The "source code" for a work means the preferred form of the work 103 | for making modifications to it. "Object code" means any non-source 104 | form of a work. 105 | 106 | A "Standard Interface" means an interface that either is an official 107 | standard defined by a recognized standards body, or, in the case of 108 | interfaces specified for a particular programming language, one that 109 | is widely used among developers working in that language. 110 | 111 | The "System Libraries" of an executable work include anything, other 112 | than the work as a whole, that (a) is included in the normal form of 113 | packaging a Major Component, but which is not part of that Major 114 | Component, and (b) serves only to enable use of the work with that 115 | Major Component, or to implement a Standard Interface for which an 116 | implementation is available to the public in source code form. A 117 | "Major Component", in this context, means a major essential component 118 | (kernel, window system, and so on) of the specific operating system 119 | (if any) on which the executable work runs, or a compiler used to 120 | produce the work, or an object code interpreter used to run it. 121 | 122 | The "Corresponding Source" for a work in object code form means all 123 | the source code needed to generate, install, and (for an executable 124 | work) run the object code and to modify the work, including scripts to 125 | control those activities. However, it does not include the work's 126 | System Libraries, or general-purpose tools or generally available free 127 | programs which are used unmodified in performing those activities but 128 | which are not part of the work. For example, Corresponding Source 129 | includes interface definition files associated with source files for 130 | the work, and the source code for shared libraries and dynamically 131 | linked subprograms that the work is specifically designed to require, 132 | such as by intimate data communication or control flow between those 133 | subprograms and other parts of the work. 134 | 135 | The Corresponding Source need not include anything that users 136 | can regenerate automatically from other parts of the Corresponding 137 | Source. 138 | 139 | The Corresponding Source for a work in source code form is that 140 | same work. 141 | 142 | 2. Basic Permissions. 143 | 144 | All rights granted under this License are granted for the term of 145 | copyright on the Program, and are irrevocable provided the stated 146 | conditions are met. This License explicitly affirms your unlimited 147 | permission to run the unmodified Program. The output from running a 148 | covered work is covered by this License only if the output, given its 149 | content, constitutes a covered work. This License acknowledges your 150 | rights of fair use or other equivalent, as provided by copyright law. 151 | 152 | You may make, run and propagate covered works that you do not 153 | convey, without conditions so long as your license otherwise remains 154 | in force. You may convey covered works to others for the sole purpose 155 | of having them make modifications exclusively for you, or provide you 156 | with facilities for running those works, provided that you comply with 157 | the terms of this License in conveying all material for which you do 158 | not control copyright. Those thus making or running the covered works 159 | for you must do so exclusively on your behalf, under your direction 160 | and control, on terms that prohibit them from making any copies of 161 | your copyrighted material outside their relationship with you. 162 | 163 | Conveying under any other circumstances is permitted solely under 164 | the conditions stated below. Sublicensing is not allowed; section 10 165 | makes it unnecessary. 166 | 167 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 168 | 169 | No covered work shall be deemed part of an effective technological 170 | measure under any applicable law fulfilling obligations under article 171 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 172 | similar laws prohibiting or restricting circumvention of such 173 | measures. 174 | 175 | When you convey a covered work, you waive any legal power to forbid 176 | circumvention of technological measures to the extent such circumvention 177 | is effected by exercising rights under this License with respect to 178 | the covered work, and you disclaim any intention to limit operation or 179 | modification of the work as a means of enforcing, against the work's 180 | users, your or third parties' legal rights to forbid circumvention of 181 | technological measures. 182 | 183 | 4. Conveying Verbatim Copies. 184 | 185 | You may convey verbatim copies of the Program's source code as you 186 | receive it, in any medium, provided that you conspicuously and 187 | appropriately publish on each copy an appropriate copyright notice; 188 | keep intact all notices stating that this License and any 189 | non-permissive terms added in accord with section 7 apply to the code; 190 | keep intact all notices of the absence of any warranty; and give all 191 | recipients a copy of this License along with the Program. 192 | 193 | You may charge any price or no price for each copy that you convey, 194 | and you may offer support or warranty protection for a fee. 195 | 196 | 5. Conveying Modified Source Versions. 197 | 198 | You may convey a work based on the Program, or the modifications to 199 | produce it from the Program, in the form of source code under the 200 | terms of section 4, provided that you also meet all of these conditions: 201 | 202 | a) The work must carry prominent notices stating that you modified 203 | it, and giving a relevant date. 204 | 205 | b) The work must carry prominent notices stating that it is 206 | released under this License and any conditions added under section 207 | 7. This requirement modifies the requirement in section 4 to 208 | "keep intact all notices". 209 | 210 | c) You must license the entire work, as a whole, under this 211 | License to anyone who comes into possession of a copy. This 212 | License will therefore apply, along with any applicable section 7 213 | additional terms, to the whole of the work, and all its parts, 214 | regardless of how they are packaged. This License gives no 215 | permission to license the work in any other way, but it does not 216 | invalidate such permission if you have separately received it. 217 | 218 | d) If the work has interactive user interfaces, each must display 219 | Appropriate Legal Notices; however, if the Program has interactive 220 | interfaces that do not display Appropriate Legal Notices, your 221 | work need not make them do so. 222 | 223 | A compilation of a covered work with other separate and independent 224 | works, which are not by their nature extensions of the covered work, 225 | and which are not combined with it such as to form a larger program, 226 | in or on a volume of a storage or distribution medium, is called an 227 | "aggregate" if the compilation and its resulting copyright are not 228 | used to limit the access or legal rights of the compilation's users 229 | beyond what the individual works permit. Inclusion of a covered work 230 | in an aggregate does not cause this License to apply to the other 231 | parts of the aggregate. 232 | 233 | 6. Conveying Non-Source Forms. 234 | 235 | You may convey a covered work in object code form under the terms 236 | of sections 4 and 5, provided that you also convey the 237 | machine-readable Corresponding Source under the terms of this License, 238 | in one of these ways: 239 | 240 | a) Convey the object code in, or embodied in, a physical product 241 | (including a physical distribution medium), accompanied by the 242 | Corresponding Source fixed on a durable physical medium 243 | customarily used for software interchange. 244 | 245 | b) Convey the object code in, or embodied in, a physical product 246 | (including a physical distribution medium), accompanied by a 247 | written offer, valid for at least three years and valid for as 248 | long as you offer spare parts or customer support for that product 249 | model, to give anyone who possesses the object code either (1) a 250 | copy of the Corresponding Source for all the software in the 251 | product that is covered by this License, on a durable physical 252 | medium customarily used for software interchange, for a price no 253 | more than your reasonable cost of physically performing this 254 | conveying of source, or (2) access to copy the 255 | Corresponding Source from a network server at no charge. 256 | 257 | c) Convey individual copies of the object code with a copy of the 258 | written offer to provide the Corresponding Source. This 259 | alternative is allowed only occasionally and noncommercially, and 260 | only if you received the object code with such an offer, in accord 261 | with subsection 6b. 262 | 263 | d) Convey the object code by offering access from a designated 264 | place (gratis or for a charge), and offer equivalent access to the 265 | Corresponding Source in the same way through the same place at no 266 | further charge. You need not require recipients to copy the 267 | Corresponding Source along with the object code. If the place to 268 | copy the object code is a network server, the Corresponding Source 269 | may be on a different server (operated by you or a third party) 270 | that supports equivalent copying facilities, provided you maintain 271 | clear directions next to the object code saying where to find the 272 | Corresponding Source. Regardless of what server hosts the 273 | Corresponding Source, you remain obligated to ensure that it is 274 | available for as long as needed to satisfy these requirements. 275 | 276 | e) Convey the object code using peer-to-peer transmission, provided 277 | you inform other peers where the object code and Corresponding 278 | Source of the work are being offered to the general public at no 279 | charge under subsection 6d. 280 | 281 | A separable portion of the object code, whose source code is excluded 282 | from the Corresponding Source as a System Library, need not be 283 | included in conveying the object code work. 284 | 285 | A "User Product" is either (1) a "consumer product", which means any 286 | tangible personal property which is normally used for personal, family, 287 | or household purposes, or (2) anything designed or sold for incorporation 288 | into a dwelling. In determining whether a product is a consumer product, 289 | doubtful cases shall be resolved in favor of coverage. For a particular 290 | product received by a particular user, "normally used" refers to a 291 | typical or common use of that class of product, regardless of the status 292 | of the particular user or of the way in which the particular user 293 | actually uses, or expects or is expected to use, the product. A product 294 | is a consumer product regardless of whether the product has substantial 295 | commercial, industrial or non-consumer uses, unless such uses represent 296 | the only significant mode of use of the product. 297 | 298 | "Installation Information" for a User Product means any methods, 299 | procedures, authorization keys, or other information required to install 300 | and execute modified versions of a covered work in that User Product from 301 | a modified version of its Corresponding Source. The information must 302 | suffice to ensure that the continued functioning of the modified object 303 | code is in no case prevented or interfered with solely because 304 | modification has been made. 305 | 306 | If you convey an object code work under this section in, or with, or 307 | specifically for use in, a User Product, and the conveying occurs as 308 | part of a transaction in which the right of possession and use of the 309 | User Product is transferred to the recipient in perpetuity or for a 310 | fixed term (regardless of how the transaction is characterized), the 311 | Corresponding Source conveyed under this section must be accompanied 312 | by the Installation Information. But this requirement does not apply 313 | if neither you nor any third party retains the ability to install 314 | modified object code on the User Product (for example, the work has 315 | been installed in ROM). 316 | 317 | The requirement to provide Installation Information does not include a 318 | requirement to continue to provide support service, warranty, or updates 319 | for a work that has been modified or installed by the recipient, or for 320 | the User Product in which it has been modified or installed. Access to a 321 | network may be denied when the modification itself materially and 322 | adversely affects the operation of the network or violates the rules and 323 | protocols for communication across the network. 324 | 325 | Corresponding Source conveyed, and Installation Information provided, 326 | in accord with this section must be in a format that is publicly 327 | documented (and with an implementation available to the public in 328 | source code form), and must require no special password or key for 329 | unpacking, reading or copying. 330 | 331 | 7. Additional Terms. 332 | 333 | "Additional permissions" are terms that supplement the terms of this 334 | License by making exceptions from one or more of its conditions. 335 | Additional permissions that are applicable to the entire Program shall 336 | be treated as though they were included in this License, to the extent 337 | that they are valid under applicable law. If additional permissions 338 | apply only to part of the Program, that part may be used separately 339 | under those permissions, but the entire Program remains governed by 340 | this License without regard to the additional permissions. 341 | 342 | When you convey a copy of a covered work, you may at your option 343 | remove any additional permissions from that copy, or from any part of 344 | it. (Additional permissions may be written to require their own 345 | removal in certain cases when you modify the work.) You may place 346 | additional permissions on material, added by you to a covered work, 347 | for which you have or can give appropriate copyright permission. 348 | 349 | Notwithstanding any other provision of this License, for material you 350 | add to a covered work, you may (if authorized by the copyright holders of 351 | that material) supplement the terms of this License with terms: 352 | 353 | a) Disclaiming warranty or limiting liability differently from the 354 | terms of sections 15 and 16 of this License; or 355 | 356 | b) Requiring preservation of specified reasonable legal notices or 357 | author attributions in that material or in the Appropriate Legal 358 | Notices displayed by works containing it; or 359 | 360 | c) Prohibiting misrepresentation of the origin of that material, or 361 | requiring that modified versions of such material be marked in 362 | reasonable ways as different from the original version; or 363 | 364 | d) Limiting the use for publicity purposes of names of licensors or 365 | authors of the material; or 366 | 367 | e) Declining to grant rights under trademark law for use of some 368 | trade names, trademarks, or service marks; or 369 | 370 | f) Requiring indemnification of licensors and authors of that 371 | material by anyone who conveys the material (or modified versions of 372 | it) with contractual assumptions of liability to the recipient, for 373 | any liability that these contractual assumptions directly impose on 374 | those licensors and authors. 375 | 376 | All other non-permissive additional terms are considered "further 377 | restrictions" within the meaning of section 10. If the Program as you 378 | received it, or any part of it, contains a notice stating that it is 379 | governed by this License along with a term that is a further 380 | restriction, you may remove that term. If a license document contains 381 | a further restriction but permits relicensing or conveying under this 382 | License, you may add to a covered work material governed by the terms 383 | of that license document, provided that the further restriction does 384 | not survive such relicensing or conveying. 385 | 386 | If you add terms to a covered work in accord with this section, you 387 | must place, in the relevant source files, a statement of the 388 | additional terms that apply to those files, or a notice indicating 389 | where to find the applicable terms. 390 | 391 | Additional terms, permissive or non-permissive, may be stated in the 392 | form of a separately written license, or stated as exceptions; 393 | the above requirements apply either way. 394 | 395 | 8. Termination. 396 | 397 | You may not propagate or modify a covered work except as expressly 398 | provided under this License. Any attempt otherwise to propagate or 399 | modify it is void, and will automatically terminate your rights under 400 | this License (including any patent licenses granted under the third 401 | paragraph of section 11). 402 | 403 | However, if you cease all violation of this License, then your 404 | license from a particular copyright holder is reinstated (a) 405 | provisionally, unless and until the copyright holder explicitly and 406 | finally terminates your license, and (b) permanently, if the copyright 407 | holder fails to notify you of the violation by some reasonable means 408 | prior to 60 days after the cessation. 409 | 410 | Moreover, your license from a particular copyright holder is 411 | reinstated permanently if the copyright holder notifies you of the 412 | violation by some reasonable means, this is the first time you have 413 | received notice of violation of this License (for any work) from that 414 | copyright holder, and you cure the violation prior to 30 days after 415 | your receipt of the notice. 416 | 417 | Termination of your rights under this section does not terminate the 418 | licenses of parties who have received copies or rights from you under 419 | this License. If your rights have been terminated and not permanently 420 | reinstated, you do not qualify to receive new licenses for the same 421 | material under section 10. 422 | 423 | 9. Acceptance Not Required for Having Copies. 424 | 425 | You are not required to accept this License in order to receive or 426 | run a copy of the Program. Ancillary propagation of a covered work 427 | occurring solely as a consequence of using peer-to-peer transmission 428 | to receive a copy likewise does not require acceptance. However, 429 | nothing other than this License grants you permission to propagate or 430 | modify any covered work. These actions infringe copyright if you do 431 | not accept this License. Therefore, by modifying or propagating a 432 | covered work, you indicate your acceptance of this License to do so. 433 | 434 | 10. Automatic Licensing of Downstream Recipients. 435 | 436 | Each time you convey a covered work, the recipient automatically 437 | receives a license from the original licensors, to run, modify and 438 | propagate that work, subject to this License. You are not responsible 439 | for enforcing compliance by third parties with this License. 440 | 441 | An "entity transaction" is a transaction transferring control of an 442 | organization, or substantially all assets of one, or subdividing an 443 | organization, or merging organizations. If propagation of a covered 444 | work results from an entity transaction, each party to that 445 | transaction who receives a copy of the work also receives whatever 446 | licenses to the work the party's predecessor in interest had or could 447 | give under the previous paragraph, plus a right to possession of the 448 | Corresponding Source of the work from the predecessor in interest, if 449 | the predecessor has it or can get it with reasonable efforts. 450 | 451 | You may not impose any further restrictions on the exercise of the 452 | rights granted or affirmed under this License. For example, you may 453 | not impose a license fee, royalty, or other charge for exercise of 454 | rights granted under this License, and you may not initiate litigation 455 | (including a cross-claim or counterclaim in a lawsuit) alleging that 456 | any patent claim is infringed by making, using, selling, offering for 457 | sale, or importing the Program or any portion of it. 458 | 459 | 11. Patents. 460 | 461 | A "contributor" is a copyright holder who authorizes use under this 462 | License of the Program or a work on which the Program is based. The 463 | work thus licensed is called the contributor's "contributor version". 464 | 465 | A contributor's "essential patent claims" are all patent claims 466 | owned or controlled by the contributor, whether already acquired or 467 | hereafter acquired, that would be infringed by some manner, permitted 468 | by this License, of making, using, or selling its contributor version, 469 | but do not include claims that would be infringed only as a 470 | consequence of further modification of the contributor version. For 471 | purposes of this definition, "control" includes the right to grant 472 | patent sublicenses in a manner consistent with the requirements of 473 | this License. 474 | 475 | Each contributor grants you a non-exclusive, worldwide, royalty-free 476 | patent license under the contributor's essential patent claims, to 477 | make, use, sell, offer for sale, import and otherwise run, modify and 478 | propagate the contents of its contributor version. 479 | 480 | In the following three paragraphs, a "patent license" is any express 481 | agreement or commitment, however denominated, not to enforce a patent 482 | (such as an express permission to practice a patent or covenant not to 483 | sue for patent infringement). To "grant" such a patent license to a 484 | party means to make such an agreement or commitment not to enforce a 485 | patent against the party. 486 | 487 | If you convey a covered work, knowingly relying on a patent license, 488 | and the Corresponding Source of the work is not available for anyone 489 | to copy, free of charge and under the terms of this License, through a 490 | publicly available network server or other readily accessible means, 491 | then you must either (1) cause the Corresponding Source to be so 492 | available, or (2) arrange to deprive yourself of the benefit of the 493 | patent license for this particular work, or (3) arrange, in a manner 494 | consistent with the requirements of this License, to extend the patent 495 | license to downstream recipients. "Knowingly relying" means you have 496 | actual knowledge that, but for the patent license, your conveying the 497 | covered work in a country, or your recipient's use of the covered work 498 | in a country, would infringe one or more identifiable patents in that 499 | country that you have reason to believe are valid. 500 | 501 | If, pursuant to or in connection with a single transaction or 502 | arrangement, you convey, or propagate by procuring conveyance of, a 503 | covered work, and grant a patent license to some of the parties 504 | receiving the covered work authorizing them to use, propagate, modify 505 | or convey a specific copy of the covered work, then the patent license 506 | you grant is automatically extended to all recipients of the covered 507 | work and works based on it. 508 | 509 | A patent license is "discriminatory" if it does not include within 510 | the scope of its coverage, prohibits the exercise of, or is 511 | conditioned on the non-exercise of one or more of the rights that are 512 | specifically granted under this License. You may not convey a covered 513 | work if you are a party to an arrangement with a third party that is 514 | in the business of distributing software, under which you make payment 515 | to the third party based on the extent of your activity of conveying 516 | the work, and under which the third party grants, to any of the 517 | parties who would receive the covered work from you, a discriminatory 518 | patent license (a) in connection with copies of the covered work 519 | conveyed by you (or copies made from those copies), or (b) primarily 520 | for and in connection with specific products or compilations that 521 | contain the covered work, unless you entered into that arrangement, 522 | or that patent license was granted, prior to 28 March 2007. 523 | 524 | Nothing in this License shall be construed as excluding or limiting 525 | any implied license or other defenses to infringement that may 526 | otherwise be available to you under applicable patent law. 527 | 528 | 12. No Surrender of Others' Freedom. 529 | 530 | If conditions are imposed on you (whether by court order, agreement or 531 | otherwise) that contradict the conditions of this License, they do not 532 | excuse you from the conditions of this License. If you cannot convey a 533 | covered work so as to satisfy simultaneously your obligations under this 534 | License and any other pertinent obligations, then as a consequence you may 535 | not convey it at all. For example, if you agree to terms that obligate you 536 | to collect a royalty for further conveying from those to whom you convey 537 | the Program, the only way you could satisfy both those terms and this 538 | License would be to refrain entirely from conveying the Program. 539 | 540 | 13. Remote Network Interaction; Use with the GNU General Public License. 541 | 542 | Notwithstanding any other provision of this License, if you modify the 543 | Program, your modified version must prominently offer all users 544 | interacting with it remotely through a computer network (if your version 545 | supports such interaction) an opportunity to receive the Corresponding 546 | Source of your version by providing access to the Corresponding Source 547 | from a network server at no charge, through some standard or customary 548 | means of facilitating copying of software. This Corresponding Source 549 | shall include the Corresponding Source for any work covered by version 3 550 | of the GNU General Public License that is incorporated pursuant to the 551 | following paragraph. 552 | 553 | Notwithstanding any other provision of this License, you have 554 | permission to link or combine any covered work with a work licensed 555 | under version 3 of the GNU General Public License into a single 556 | combined work, and to convey the resulting work. The terms of this 557 | License will continue to apply to the part which is the covered work, 558 | but the work with which it is combined will remain governed by version 559 | 3 of the GNU General Public License. 560 | 561 | 14. Revised Versions of this License. 562 | 563 | The Free Software Foundation may publish revised and/or new versions of 564 | the GNU Affero General Public License from time to time. Such new versions 565 | will be similar in spirit to the present version, but may differ in detail to 566 | address new problems or concerns. 567 | 568 | Each version is given a distinguishing version number. If the 569 | Program specifies that a certain numbered version of the GNU Affero General 570 | Public License "or any later version" applies to it, you have the 571 | option of following the terms and conditions either of that numbered 572 | version or of any later version published by the Free Software 573 | Foundation. If the Program does not specify a version number of the 574 | GNU Affero General Public License, you may choose any version ever published 575 | by the Free Software Foundation. 576 | 577 | If the Program specifies that a proxy can decide which future 578 | versions of the GNU Affero General Public License can be used, that proxy's 579 | public statement of acceptance of a version permanently authorizes you 580 | to choose that version for the Program. 581 | 582 | Later license versions may give you additional or different 583 | permissions. However, no additional obligations are imposed on any 584 | author or copyright holder as a result of your choosing to follow a 585 | later version. 586 | 587 | 15. Disclaimer of Warranty. 588 | 589 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 590 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 591 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 592 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 593 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 594 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 595 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 596 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 597 | 598 | 16. Limitation of Liability. 599 | 600 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 601 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 602 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 603 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 604 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 605 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 606 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 607 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 608 | SUCH DAMAGES. 609 | 610 | 17. Interpretation of Sections 15 and 16. 611 | 612 | If the disclaimer of warranty and limitation of liability provided 613 | above cannot be given local legal effect according to their terms, 614 | reviewing courts shall apply local law that most closely approximates 615 | an absolute waiver of all civil liability in connection with the 616 | Program, unless a warranty or assumption of liability accompanies a 617 | copy of the Program in return for a fee. 618 | 619 | END OF TERMS AND CONDITIONS 620 | 621 | How to Apply These Terms to Your New Programs 622 | 623 | If you develop a new program, and you want it to be of the greatest 624 | possible use to the public, the best way to achieve this is to make it 625 | free software which everyone can redistribute and change under these terms. 626 | 627 | To do so, attach the following notices to the program. It is safest 628 | to attach them to the start of each source file to most effectively 629 | state the exclusion of warranty; and each file should have at least 630 | the "copyright" line and a pointer to where the full notice is found. 631 | 632 | 633 | Copyright (C) 634 | 635 | This program is free software: you can redistribute it and/or modify 636 | it under the terms of the GNU Affero General Public License as published by 637 | the Free Software Foundation, either version 3 of the License, or 638 | (at your option) any later version. 639 | 640 | This program is distributed in the hope that it will be useful, 641 | but WITHOUT ANY WARRANTY; without even the implied warranty of 642 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 643 | GNU Affero General Public License for more details. 644 | 645 | You should have received a copy of the GNU Affero General Public License 646 | along with this program. If not, see . 647 | 648 | Also add information on how to contact you by electronic and paper mail. 649 | 650 | If your software can interact with users remotely through a computer 651 | network, you should also make sure that it provides a way for users to 652 | get its source. For example, if your program is a web application, its 653 | interface could display a "Source" link that leads users to an archive 654 | of the code. There are many ways you could offer source, and different 655 | solutions will be better for different programs; see section 13 for the 656 | specific requirements. 657 | 658 | You should also get your employer (if you work as a programmer) or school, 659 | if any, to sign a "copyright disclaimer" for the program, if necessary. 660 | For more information on this, and how to apply and follow the GNU AGPL, see 661 | . 662 | --------------------------------------------------------------------------------