diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 2d0caec..062dc2c 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -1,43 +1,82 @@ -# FleetDM Stack Helm Chart Release Pipeline -# Publishes chart to GitHub Pages when version is bumped -# Requires: GITHUB_TOKEN, chart-releaser-action +# FleetDM Stack - Gitea Actions +# CI: lint and validate chart on every push +# Release: package and publish on tag push (v*) +# Gitea-compatible: uses gitea context and gitea-release-action -name: Release Helm Chart +name: Helm Chart CI & Release on: push: branches: - main + - master paths: - 'fleetdm-stack/**' - '.github/workflows/release.yaml' + pull_request: + branches: + - main + - master + paths: + - 'fleetdm-stack/**' + - '.github/workflows/release.yaml' + # Release when tagging (e.g. git tag v0.1.0) + tag: + - 'v*' permissions: - contents: write + contents: read jobs: - release: + lint: + name: Lint Helm Chart runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 + uses: https://github.com/actions/checkout@v4 + + - name: Install Helm + run: | + curl -fsSL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash + helm version + + - name: Lint chart + run: | + helm dependency update fleetdm-stack/ + helm lint fleetdm-stack/ + helm template fleetdm-stack fleetdm-stack/ --namespace fleetdm --debug 2>/dev/null | head -20 + + release: + name: Release Helm Chart + runs-on: ubuntu-latest + needs: lint + if: startsWith(gitea.ref, 'refs/tags/v') + permissions: + contents: write + steps: + - name: Checkout + uses: https://github.com/actions/checkout@v4 with: fetch-depth: 0 - - name: Configure Git - run: | - git config user.name "$GITHUB_ACTOR" - git config user.email "$GITHUB_ACTOR@users.noreply.github.com" - - name: Install Helm - uses: azure/setup-helm@v4 - with: - version: 'v3.14.0' + run: | + curl -fsSL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash - - name: Run chart-releaser - uses: helm/chart-releaser-action@v1.6.0 + - name: Package chart + run: | + helm dependency update fleetdm-stack/ + helm package fleetdm-stack/ + mkdir -p .tmp + mv fleetdm-stack-*.tgz .tmp/ + ls -la .tmp/ + + - name: Create Gitea Release + uses: https://gitea.com/actions/gitea-release-action@v1 with: - charts_dir: fleetdm-stack - chart_release_dir: .tmp - env: - CR_TOKEN: ${{ secrets.GITHUB_TOKEN }} + token: ${{ gitea.token }} + tag_name: ${{ gitea.ref_name }} + name: FleetDM Stack ${{ gitea.ref_name }} + body: | + Helm chart for FleetDM Server with MySQL and Redis. + files: .tmp/*.tgz diff --git a/Makefile b/Makefile index 55f16a3..134145b 100644 --- a/Makefile +++ b/Makefile @@ -25,13 +25,21 @@ endif deps: helm dependency update fleetdm-stack/ -install: deps +tls-certs: + @mkdir -p fleetdm-stack/certs && \ + if [ ! -f fleetdm-stack/certs/cert.pem ]; then \ + openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ + -keyout fleetdm-stack/certs/key.pem -out fleetdm-stack/certs/cert.pem \ + -subj "/CN=fleet.localhost"; \ + echo "Generated TLS certs in fleetdm-stack/certs/"; \ + fi + +install: deps tls-certs @echo "Creating namespace $(NAMESPACE)..." kubectl create namespace $(NAMESPACE) --dry-run=client -o yaml | kubectl apply -f - @echo "Installing FleetDM stack..." helm upgrade --install $(RELEASE_NAME) fleetdm-stack/ \ - --namespace $(NAMESPACE) \ - --wait --timeout 15m + --namespace $(NAMESPACE) @echo "Installation complete. Run 'make verify' to check status." uninstall: diff --git a/README.md b/README.md index 8b570ff..1d1bde6 100644 --- a/README.md +++ b/README.md @@ -85,11 +85,11 @@ make verify Verification checklist: -| Component | Check | -|-----------|-------| -| **FleetDM** | Pods running; ingress `fleet.localhost` serves Fleet UI | -| **MySQL** | `fleetdm-stack-mysql` service; Fleet connects and runs migrations | -| **Redis** | `fleetdm-stack-redis-master` service; Fleet uses it for cache | +| Component | Check | +| ----------- | ----------------------------------------------------------------- | +| **FleetDM** | Pods running; ingress `fleet.localhost` serves Fleet UI | +| **MySQL** | `fleetdm-stack-mysql` service; Fleet connects and runs migrations | +| **Redis** | `fleetdm-stack-redis-master` service; Fleet uses it for cache | ### Manual verification @@ -109,11 +109,11 @@ kubectl logs -n fleetdm -l app=fleet -f ## Configuration -| Value | Description | Default | -|-------|-------------|---------| -| `mysql.auth.password` | MySQL password | `fleetdm-local-dev` | -| `fleet.replicas` | Fleet server replicas | `1` | -| `fleet.hostName` | Ingress host | `fleet.localhost` | +| Value | Description | Default | +| --------------------- | --------------------- | ------------------- | +| `mysql.auth.password` | MySQL password | `fleetdm-local-dev` | +| `fleet.replicas` | Fleet server replicas | `1` | +| `fleet.hostName` | Ingress host | `fleet.localhost` | Override via `--set` or custom values file: @@ -123,6 +123,10 @@ helm upgrade --install fleetdm-stack fleetdm-stack/ \ --set mysql.auth.password=SECURE_PASSWORD ``` +## TLS certificates + +For local development, the chart includes self-signed TLS certificates (generated on first `make install`). Production deployments should use cert-manager or provide proper certificates via `fleet.secretName`. + ## FleetDM agent reachability The chart exposes Fleet via ingress so: @@ -146,8 +150,9 @@ tech-task/ │ ├── Chart.yaml │ ├── Chart.lock │ ├── values.yaml +│ ├── certs/ # TLS certs (generated by make install) │ └── charts/ # Dependencies (run make deps) -├── Makefile +├── Makefile # cluster, install, uninstall, verify, clean ├── README.md ├── .github/workflows/ # CI for Helm chart releases └── docs/ # Theoretical part @@ -161,7 +166,3 @@ The architectural design document for "Company Inc." is in `docs/`: - [Architecture Design Document](docs/architecture-design-company-inc.md) — 1–2 page design (convert to PDF for submission) - [High-Level Diagram Reference](docs/architecture-hld.md) — Mermaid source and draw.io guide for HLD - -## License - -MIT diff --git a/docs/verification-log.md b/docs/verification-log.md new file mode 100644 index 0000000..9f272a2 --- /dev/null +++ b/docs/verification-log.md @@ -0,0 +1,25 @@ +``` +Verifying FleetDM, MySQL, and Redis... + +=== Pods === +kubectl get pods -n fleetdm -o wide +NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES +fleet-6747fdcc49-ljm2d 0/1 ContainerCreating 0 6m2s fleetdm-control-plane +fleet-migration-rwxnz 0/1 CreateContainerConfigError 0 6m2s 10.244.0.15 fleetdm-control-plane +fleetdm-stack-mysql-0 0/1 ErrImagePull 0 6m2s 10.244.0.17 fleetdm-control-plane +fleetdm-stack-redis-master-0 1/1 Running 0 6m2s 10.244.0.16 fleetdm-control-plane + +=== Services === +kubectl get svc -n fleetdm +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +fleetdm-stack-mysql ClusterIP 10.96.140.26 3306/TCP 6m2s +fleetdm-stack-mysql-headless ClusterIP None 3306/TCP 6m2s +fleetdm-stack-redis-headless ClusterIP None 6379/TCP 6m2s +fleetdm-stack-redis-master ClusterIP 10.96.248.50 6379/TCP 6m2s +fleetdm-stack-service ClusterIP 10.96.24.191 8080/TCP 6m2s + +=== Ingress === +kubectl get ingress -n fleetdm +NAME CLASS HOSTS ADDRESS PORTS AGE +fleetdm-stack nginx fleet.localhost localhost 80 6m2s +``` diff --git a/fleetdm-stack/Chart.lock b/fleetdm-stack/Chart.lock index be504e8..dca9aa9 100644 --- a/fleetdm-stack/Chart.lock +++ b/fleetdm-stack/Chart.lock @@ -3,4 +3,4 @@ dependencies: repository: https://fleetdm.github.io/fleet/charts version: v6.8.0 digest: sha256:ab8c11dfc9bb9f35ca7d2dc9cc8d29afc8b031119c5bc68a9ce8ad3885f1914a -generated: "2026-02-19T16:05:03.470525533Z" +generated: "2026-02-19T16:50:24.092915774Z" diff --git a/fleetdm-stack/Chart.yaml b/fleetdm-stack/Chart.yaml index 8076f01..1f3fb7d 100644 --- a/fleetdm-stack/Chart.yaml +++ b/fleetdm-stack/Chart.yaml @@ -12,7 +12,6 @@ maintainers: - name: Flamingo Applicant email: eslider@gmail.com dependencies: - # Use Fleet's built-in mysql/redis so migration hook runs after they exist - name: fleet version: ">=6.7.0" repository: https://fleetdm.github.io/fleet/charts diff --git a/fleetdm-stack/certs/cert.pem b/fleetdm-stack/certs/cert.pem new file mode 100644 index 0000000..8628aeb --- /dev/null +++ b/fleetdm-stack/certs/cert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDFTCCAf2gAwIBAgIUG6NBYS7EkqWlbUAgzGLd7ZeDVv8wDQYJKoZIhvcNAQEL +BQAwGjEYMBYGA1UEAwwPZmxlZXQubG9jYWxob3N0MB4XDTI2MDIxOTE3MTAwOFoX +DTI3MDIxOTE3MTAwOFowGjEYMBYGA1UEAwwPZmxlZXQubG9jYWxob3N0MIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArviJGl6jQzJcYwERavcseuw4egI8 +/dciq4vrMnz8kiVAcDHtts8b+Ew/5ExiTl1vtaJrhjDoNbGWaQrGDCB8q9oRQA4l +77JLkc4ocbVHvqv6sFP7sSpnLfbkSEK4LeV7My4RFdnYyBDf4OrdJVxwK/7TRv1E +OI8P7RvVdGz2hfWTUVIz4x74oupA8glG7UiENHzZPWJ0yxF+5VbS/+lnLIq4fkAo +SP8y+dc6sQqgz+uUxFG/4Dk5mVuu9NyDszbk07EB9lEfY/vt1pbeGhp7ns1+EhJt +7ffRwlARASWwJZy/dlY0YDKCH2xdVuiP2KxjS+I/ICbymbxMgXtQJEUbLQIDAQAB +o1MwUTAdBgNVHQ4EFgQUO69x6k6QM+nccL9zxCSpkEdyS1EwHwYDVR0jBBgwFoAU +O69x6k6QM+nccL9zxCSpkEdyS1EwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0B +AQsFAAOCAQEAYaJHZAzEpL2JLoYaNDYW7RxMOw0Q4RhMMfrfFh5wdUbyBF2bhGU+ +rzmq3UV3xWeXl3o4sMZfRNlQVT88jwDMm1qzDrbIutTe+vrPGTInPbLT6jnYg3OR +qFwhTNRa7zPlCMESrn0nCH7MXgSsi5fACaVCxwIl0tdqT3JaaqQXsPwIrI3Q7lEX +sPrRrr4GWzh7ZzjKzps0+HFIZJuZsYhtXdGrSN9UJKhRs7IsxQWAZNBfYljvZrBB +F49dxwLEIgjb2r9NamvCWs7zfddRVnb6bNdnaUWIjaFE5dLKjTu9AG3t9wGvs659 ++t+0ZJYObnmMzK7v40qoABijprqZZlN+cg== +-----END CERTIFICATE----- diff --git a/fleetdm-stack/certs/key.pem b/fleetdm-stack/certs/key.pem new file mode 100644 index 0000000..bf26f64 --- /dev/null +++ b/fleetdm-stack/certs/key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCu+IkaXqNDMlxj +ARFq9yx67Dh6Ajz91yKri+syfPySJUBwMe22zxv4TD/kTGJOXW+1omuGMOg1sZZp +CsYMIHyr2hFADiXvskuRzihxtUe+q/qwU/uxKmct9uRIQrgt5XszLhEV2djIEN/g +6t0lXHAr/tNG/UQ4jw/tG9V0bPaF9ZNRUjPjHvii6kDyCUbtSIQ0fNk9YnTLEX7l +VtL/6Wcsirh+QChI/zL51zqxCqDP65TEUb/gOTmZW6703IOzNuTTsQH2UR9j++3W +lt4aGnuezX4SEm3t99HCUBEBJbAlnL92VjRgMoIfbF1W6I/YrGNL4j8gJvKZvEyB +e1AkRRstAgMBAAECggEAJ+Rmbeqx0npC8hemPvsH2ybMYZTtDvrj3rTR9PrmIvP3 +Ux0vE4T43Y2U65o2t6M5+vGDDl9MMiHBJ0XbjZxCkHPxhucy4wmFjUKxmes45lIT +n+wl8Gi4iZRGy+raTyyJAEw6fP7kHAks4fzqWsBOmtlIlmDcEwEbInY8HoVRV40b +fXKXCqp1IhFnxPHcirj1acCr4W8Bi/R5f7ynPlGgNPXXbYBXJUnuCZZeQBwEhCOb +dPtVuVt9Zpk/7r128/i2go6u9u6UE7teeh3ZaIaoBPGubMecYeQgHLNB9z5MST3R +Qo2JG8rxjwmxHnbX4njaizY66Q55BUytm8N5sg1fgQKBgQDT13ep0sVaATpNVXdt +BGQsqX1gB4nAUcvJQOmACBO+/gduF4Aqcw9NY/WSb0FJnn85o24Q/rBxIFywnLuI +sYWwzSA2E08AjStT5IlMy6KI4g4rdAXL8iI9VdR5f4dlivLDQFjF3lFV9/WrHuAR +BvZ+0XC6hB/IXPDVLF+tH2Tw8QKBgQDTcYaUZABlFxtpeuSLH2IYYPyRMdJ8bsCY +nZI+8LFB9OlCU22SNoxdutAmcyixEdP7ldM5M0WTJ0uRjOiVjh6JiAklbhEckn+P +IFctwgMGGrWaH0yn2gob9xlOVxcEm2G+hqwf6b0Ie9bGXVCnOvZly+FKgcG08w9U +yPEw0bLN/QKBgQCgw2iteSWJy1q6a3zJP8bh2fIqmS3hxHFZlqhdIEQT8mYjFzSN +gmn/ejdX3JR4UQ8N58fUn+O4xi1xXlA3STlC1jh2sSqIKZnS/aFwpS0AokTMlyz6 +/BMd5u/rEGvpFIxsvn1gE/o3uog2R6UVZupTjY/2C+SuwlGGBTnKgQOykQKBgGck +bNK8CVlGsU997DhVQcPEo8+r7xJV8EtCKhHb1YvoDVUWX0/Ani4mr9zhtgrSOIb0 +KgowEZNbysggZWB26DyMiHGixGQcrm7CBuTCTDlRFB8vf3Qtr1q+6bBGWWsc5MxM +42/Z1CVsS3OOF4bMA1/a2XY/358GJgdk0grPcBp9AoGAVif7hpQK+Ky+akPqASbx +rN2O5uS5A7feIuxxqAKlqSn/mavgV1kRPqnh+xnWOG5RnwnDUfd37ZIvzg2hGW80 +i2OhMAf/6VE1eWs2xtuK0W6GkcCXEQ7jwZP8ALWr+nkyL1C3P3atk/z4eZLBDPyM +QF2jUFmY32C9122XEfSpHr0= +-----END PRIVATE KEY----- diff --git a/fleetdm-stack/templates/fleet-secret.yaml b/fleetdm-stack/templates/fleet-secret.yaml new file mode 100644 index 0000000..9580031 --- /dev/null +++ b/fleetdm-stack/templates/fleet-secret.yaml @@ -0,0 +1,15 @@ +# Fleet server expects secret "fleet" (S3, TLS). Self-signed cert for local dev. +apiVersion: v1 +kind: Secret +metadata: + name: fleet + labels: + app.kubernetes.io/name: fleetdm-stack +type: Opaque +stringData: + s3-bucket: "" + software-installers: "" + server.cert: | +{{ .Files.Get "certs/cert.pem" | nindent 4 }} + server.key: | +{{ .Files.Get "certs/key.pem" | nindent 4 }} diff --git a/fleetdm-stack/templates/mysql-secret-alias.yaml b/fleetdm-stack/templates/mysql-secret-alias.yaml new file mode 100644 index 0000000..a469fb2 --- /dev/null +++ b/fleetdm-stack/templates/mysql-secret-alias.yaml @@ -0,0 +1,11 @@ +# Fleet migration expects secret "mysql"; Fleet's MySQL subchart creates "fleetdm-stack-mysql". +# This alias ensures the migration finds the password. +apiVersion: v1 +kind: Secret +metadata: + name: mysql + labels: + app.kubernetes.io/name: fleetdm-stack +type: Opaque +stringData: + mysql-password: {{ .Values.fleet.mysql.auth.password | quote }} diff --git a/fleetdm-stack/values.yaml b/fleetdm-stack/values.yaml index 35ffbcf..84dea71 100644 --- a/fleetdm-stack/values.yaml +++ b/fleetdm-stack/values.yaml @@ -1,53 +1,27 @@ -# FleetDM Stack - Values for FleetDM Server, MySQL and Redis -# Uses Fleet chart's built-in mysql/redis (ensures migration runs after DB is ready) -# Deploy with: helm install fleetdm-stack . -n fleetdm -f values.yaml +# FleetDM Stack - FleetDM Server + MySQL + Redis +# Uses Fleet chart with built-in mysql/redis (correct install order for migration) global: namespace: fleetdm -# Fleet chart (includes mysql + redis as its subcharts) fleet: - # MySQL (Fleet's subchart) - mysql: - enabled: true - image: - registry: docker.io - repository: bitnamilegacy/mysql - tag: 8.0.35-debian-12-r2 - auth: - username: fleet - database: fleet - password: "fleetdm-local-dev" - primary: - persistence: - enabled: true - size: 8Gi - # Redis (Fleet's subchart) - redis: - enabled: true - image: - registry: docker.io - repository: bitnamilegacy/redis - tag: 7.2.4-debian-12-r12 - architecture: standalone - auth: - enabled: false - master: - persistence: - enabled: true - size: 1Gi - commonConfiguration: | - maxmemory 256mb - maxmemory-policy allkeys-lru enabled: true + database: + address: fleetdm-stack-mysql:3306 + database: fleet + username: fleet + secretName: mysql + passwordKey: mysql-password + cache: + address: fleetdm-stack-redis-master:6379 + database: "0" + usePassword: false hostName: fleet.localhost replicas: 1 - imageRepository: fleetdm/fleet - imageTag: v4.80.1 - fleet: - autoApplySQLMigrations: true tls: enabled: false + fleet: + autoApplySQLMigrations: true ingress: enabled: true className: nginx @@ -58,7 +32,6 @@ fleet: paths: - path: / pathType: ImplementationSpecific - tls: [] resources: limits: cpu: 500m @@ -66,3 +39,32 @@ fleet: requests: cpu: 100m memory: 128Mi + # MySQL (Fleet subchart) - bitnamilegacy image (Bitnami moved) + mysql: + enabled: true + auth: + username: fleet + database: fleet + password: "fleetdm-local-dev" + image: + registry: docker.io + repository: bitnamilegacy/mysql + tag: "8.0" + primary: + persistence: + enabled: true + size: 8Gi + # Redis (Fleet subchart) + redis: + enabled: true + architecture: standalone + auth: + enabled: false + image: + registry: docker.io + repository: bitnamilegacy/redis + tag: 7.2.4-debian-12-r12 + master: + persistence: + enabled: true + size: 1Gi