diff --git a/.commitlintrc.js b/.commitlintrc.js deleted file mode 100644 index 28c36622..00000000 --- a/.commitlintrc.js +++ /dev/null @@ -1,14 +0,0 @@ -import commitlintConfigConventional from "@commitlint/config-conventional" - -const ruleMaxLineLength = - commitlintConfigConventional.rules["body-max-line-length"]; - -ruleMaxLineLength[0] = process.env.CI === "true" ? 1 : 2; - -export default { - extends: ["@commitlint/config-conventional"], - rules: { - "body-max-line-length": ruleMaxLineLength, - "footer-max-line-length": ruleMaxLineLength, - }, -}; diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index f78d206a..46823ac1 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,12 +1 @@ -# These are supported funding model platforms - -github: [dargmuesli] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] -patreon: # Replace with a single Patreon username -open_collective: # Replace with a single Open Collective username -ko_fi: # Replace with a single Ko-fi username -tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel -community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry -liberapay: # Replace with a single Liberapay username -issuehunt: # Replace with a single IssueHunt username -otechie: # Replace with a single Otechie username -custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] +github: [dargmuesli] \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8d408ce0..8897680b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,12 +20,30 @@ jobs: build: needs: ci-optimization if: needs.ci-optimization.outputs.continue == 'true' - name: dargstack rgen - uses: dargmuesli/github-actions/.github/workflows/dargstack-rgen.yml@661e39fe1c9e484d94c6a5a9d4c9946d57c41771 # 5.1.0 + name: Update generated docs + runs-on: ubuntu-latest permissions: - contents: read - with: - APT_PACKAGES: mkcert + contents: write + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.head_ref || github.ref_name }} + - name: Regenerate docs + run: | + go install github.com/dargstack/dargstack/v4/cmd/dargstack@latest + export PATH="$(go env GOPATH)/bin:$PATH" + dargstack document + - name: Commit and push updated docs + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git add artifacts/docs/ + if git diff --staged --quiet; then + echo "Docs are already up to date" + else + git commit -m "chore: update generated docs" + git push + fi release-semantic: needs: build name: Semantic Release diff --git a/.husky/commit-msg b/.husky/commit-msg deleted file mode 100755 index 2b99f23e..00000000 --- a/.husky/commit-msg +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh - -export NVM_DIR="$HOME/.nvm" -# shellcheck source=/dev/null -[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" - -pnpm commitlint --edit "$1" \ No newline at end of file diff --git a/.husky/pre-commit b/.husky/pre-commit deleted file mode 100644 index 862a47b8..00000000 --- a/.husky/pre-commit +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh - -export NVM_DIR="$HOME/.nvm" -# shellcheck source=/dev/null -[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" - -pnpm dargstack_rgen --validate diff --git a/.nvmrc b/.nvmrc deleted file mode 100644 index a45fd52c..00000000 --- a/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -24 diff --git a/.releaserc.json b/.releaserc.json index 38b975bb..1f79157c 100644 --- a/.releaserc.json +++ b/.releaserc.json @@ -15,9 +15,7 @@ } ], "@semantic-release/changelog", - "@semantic-release/npm", "@semantic-release/github", "@semantic-release/git" - ], - "tagFormat": "${version}" + ] } diff --git a/Dockerfile.md b/Dockerfile.md new file mode 100644 index 00000000..9a2d53fb --- /dev/null +++ b/Dockerfile.md @@ -0,0 +1,3 @@ +# +FROM ghcr.io/dargstack/dargstack:4.0.0-beta.7 +# diff --git a/README.md b/README.md deleted file mode 100644 index 7b8e6434..00000000 --- a/README.md +++ /dev/null @@ -1,411 +0,0 @@ -# stack - - -The Docker stack configuration for [vibetype.app](https://vibetype.app/). - -This project is deployed in accordance to the [DargStack template](https://github.com/dargstack/dargstack_template/) to make deployment a breeze. It is closely related to [Vibetype's source code](https://github.com/maevsi/vibetype/). - -## Table of Contents - - - 1. [x-shared](#x-shared) - - 2. [secrets](#secrets) - - 3. [services](#services) - - 4. [volumes](#volumes) - - -## x-shared - - - - ### `zammad-service` - - You can access the helpdesk at [zammad.app.localhost](https://zammad.app.localhost/). - - -## secrets - - - - ### `elasticsearch-keystore_password` - - The search engine's password for the keystore. - - - ### `elasticsearch-password` - - The search engine's password for the default user. - - - ### `grafana_admin_email` - - The observation dashboard's admin email. - - - ### `grafana_admin_password` - - The observation dashboard's admin password. - - - ### `grafana_admin_user` - - The observation dashboard's admin user. - - - ### `grafana_discord_webhook` - - The observation dashboard's contact point for Discord. - - - ### `jobber_aliases` - - The job scheduler's SMTP client mail alias. - - - ### `jobber_aws-bucket` - - The job scheduler's AWS bucket name. - - - ### `jobber_aws-configuration` - - The job scheduler's AWS configuration. - - - ### `jobber_aws-credentials` - - The job scheduler's AWS credentials. - - - ### `jobber_msmtprc` - - The job scheduler's SMTP client configuration. - - - ### `portainer_admin-password` - - The container manager's admin password. - - - ### `postgraphile_connection` - - The GraphQL API's database URI. - - - ### `postgraphile_jwt-secret` - - The GraphQL API's JWT secret. - - - ### `postgraphile_owner-connection` - - The GraphQL API's database owner URI. - - - ### `postgres-backup_db` ![production](https://img.shields.io/badge/-production-informational.svg?style=flat-square) - - The database's name. - - - ### `postgres_db` - - The database's name. - - - ### `postgres_password` - - The database's password. - - - ### `postgres_role_service_grafana_password` - - The password of the observation dashboard's database role. - - - ### `postgres_role_service_grafana_username` - - The username of the observation dashboard's database role. - - - ### `postgres_role_service_postgraphile_password` - - The password of the GraphQL API database wrapper's database role. - - - ### `postgres_role_service_postgraphile_username` - - The username of the GraphQL API database wrapper's database role. - - - ### `postgres_role_service_vibetype_password` - - The `tusd` database role's password. - - - ### `postgres_role_service_vibetype_username` - - The `tusd` database role's password. - - - ### `postgres_role_service_zammad_password` - - The password of the customer service database role. - - - ### `postgres_role_service_zammad_username` - - The username of the customer service database role. - - - ### `postgres_user` - - The database's default user. - - - ### `reccoom_ingest-api-key` - - The AI provider's API key for the recommendation engine. - - - ### `reccoom_openai-api-key` - - The AI provider's API key for the recommendation engine. - - - ### `sqitch_target` - - The database change management application's database connection string. - - - ### `traefik_cf-dns-api-token` ![production](https://img.shields.io/badge/-production-informational.svg?style=flat-square) - - The DNS provider's DNS API token. - - - ### `traefik_cf-zone-api-token` ![production](https://img.shields.io/badge/-production-informational.svg?style=flat-square) - - The DNS provider's zone API token. - - - ### `tusd_aws` - - The upload service's s3 credentials file. - - - ### `vibetype_api-notification-secret` - - The notification endpoint's secret. - - - ### `vibetype_aws-credentials` - - The cloud computing provider's user credentials. - - - ### `vibetype_firebase-service-account-credentials` - - The notification provider's service account credentials. - - - ### `vibetype_monday` - - The project management software's configuration. - - - ### `vibetype_openai-api-key` - - The AI provider's API key for the frontend. - - - ### `vibetype_turnstile-key` - - The captcha provider's application key. - - -## services - - - - ### `adminer` - - You can access the database's frontend at [adminer.app.localhost](https://adminer.app.localhost/). - This information is required for login: - - | | | - | -------- | ------------------- | - | System | PostgreSQL | - | Server | postgres | - | Username | [postgres_user] | - | Password | [postgres_password] | - | Database | [postgres_db] | - - Values in square brackets are [Docker secrets](https://docs.docker.com/engine/swarm/secrets/). - - - ### `cloudflared` ![production](https://img.shields.io/badge/-production-informational.svg?style=flat-square) - - You can configure the secure tunnel at [dash.cloudflare.com](https://dash.cloudflare.com/). - - - ### `debezium` - - You can see how changes in the database end up in the event stream using `redpanda-console`. - - - ### `debezium-postgres-connector` - - You can check the database connector's setup logs using `portainer`. - - - ### `elasticsearch` - - You cannot access the search engine via a web interface. - - - ### `geoip` - - You cannot access the ip geolocator via a web interface. - - - ### `grafana` - - You can access the observation dashboard at [grafana.app.localhost](https://grafana.app.localhost/). - - - ### `jobber` - - You cannot access the jobber via a web interface. - - - ### `memcached` - - You cannot access the caching system via a web interface. - - - ### `minio` ![development](https://img.shields.io/badge/-development-informational.svg?style=flat-square) - - You can access the s3 console at [minio.app.localhost](https://minio.app.localhost/). - You can access the s3 api service at [s3.app.localhost](https://s3.app.localhost/) if you want to access via cli from outside the stack. - - - ### `portainer` - - You can access the container manager's frontend at [portainer.app.localhost](https://portainer.app.localhost/). - - - ### `portainer-agent` - - You cannot access the container manager's agent directly. - - - ### `postgraphile` - - You can access the GraphQL API for the PostgreSQL database at [postgraphile.app.localhost](https://postgraphile.app.localhost/). - - - ### `postgres` - - You can access the database via `adminer`. - - - ### `postgres_backup` ![production](https://img.shields.io/badge/-production-informational.svg?style=flat-square) - - You cannot access the database backup directly. - - - ### `prometheus` - - You can access the metrics monitoring at [prometheus.app.localhost](https://prometheus.app.localhost/). - - - ### `reccoom` - - You cannot access the recommendation service directly. - - - ### `reccoom_postgres` - - You can access reccoom's database via `adminer`. - - - ### `redis` - - You cannot access the caching system via a web interface. - - - ### `redpanda` - - You can access the event streaming platform's ui as described under `redpanda-console`. - - - ### `redpanda-console` - - You can access the event streaming platform's ui at [redpanda.app.localhost](https://redpanda.app.localhost/). - - - ### `sqitch` - - You cannot access the database migrations directly. - - - ### `traefik` - - You can access the reverse proxy's dashboard at [traefik.app.localhost](https://traefik.app.localhost/). - - - ### `traefik_certs-dumper` ![production](https://img.shields.io/badge/-production-informational.svg?style=flat-square) - - You cannot access the reverse proxy's certificate helper directly. - - - ### `tusd` - - You can access the upload service at [tusd.app.localhost](https://tusd.app.localhost/). - - - ### `vibetype` - - You can access the main project's frontend at [app.localhost](https://app.localhost/). - - - ### `zammad-backup` - - You cannot access the helpdesk backup service via a web interface. - - - ### `zammad-init` - - You cannot access the helpdesk initialization service via a web interface. - - - ### `zammad-nginx` - - You can access the helpdesk at [zammad.app.localhost](https://zammad.app.localhost/). - - - ### `zammad-railsserver` - - You cannot access the helpdesk application server directly. - - - ### `zammad-scheduler` - - You cannot access the helpdesk scheduler directly. - - - ### `zammad-websocket` - - You cannot access the helpdesk websocket server directly. - - -## volumes - - - - ### `acme_data` ![production](https://img.shields.io/badge/-production-informational.svg?style=flat-square) - - The reverse proxy's certificate data. - - - ### `debezium_kafka_configuration` - - The change data capture's configuration. - - - ### `debezium_kafka_data` - - The change data capture's data. - - - ### `debezium_kafka_logs` - - The change data capture's logs. - - - ### `elasticsearch-configuration` - - The search engine's configuration. - - - ### `elasticsearch_data` - - The search engine's data. - - - ### `grafana_data` - - The observation dashboard's data. - - - ### `minio_data` - - The s3 server's data. - - - ### `pnpm_data` - - The node package manager's data. - - - ### `portainer_data` - - The container manager's data. - - - ### `postgraphile_data` - - The GraphQL API's data. - - - ### `postgres_data` - - The database's data. - - - ### `prometheus_data` - - The metrics monitoring's data. - - - ### `reccoom_postgres_data` - - The recommendation database's data. - - - ### `redis_data` - - The caching system's data. - - - ### `redpanda_data` - - The message queue's data. - - - ### `vibetype_data` - - The frontend's data. - - - ### `zammad-backup_data` - - The helpdesk backup's data. - - - ### `zammad_data` - - The helpdesk's data. - - diff --git a/artifacts/.gitignore b/artifacts/.gitignore new file mode 100644 index 00000000..87bd3818 --- /dev/null +++ b/artifacts/.gitignore @@ -0,0 +1,4 @@ +audit-log/ +certificates/ +secrets/ +.env.merged \ No newline at end of file diff --git a/artifacts/docs/README.md b/artifacts/docs/README.md new file mode 100644 index 00000000..984f0154 --- /dev/null +++ b/artifacts/docs/README.md @@ -0,0 +1,172 @@ +# vibetype + +The Docker stack configuration for [vibetype.app](https://vibetype.app/). + +## Profiles + +### analytics + +Services: grafana, prometheus + +### default + +Services: adminer, cloudflared, portainer, portainer-agent, postgraphile, postgres, sqitch, traefik, vibetype + +### event-streaming + +Services: debezium, debezium-postgres-connector, redpanda, redpanda-console + +### recommendation + +Services: reccoom, reccoom_postgres + +### upload + +Services: minio, tusd + +### zammad + +Services: elasticsearch, memcached, redis, zammad-backup, zammad-init, zammad-nginx, zammad-railsserver, zammad-scheduler, zammad-websocket + +## Services + +### adminer + +You can access the database's frontend at [adminer.app.localhost](https://adminer.app.localhost/). +This information is required for login: + +| | | +| -------- | ------------------- | +| System | PostgreSQL | +| Server | postgres | +| Username | [postgres-user] | +| Password | [postgres-password] | +| Database | [postgres-db] | + +Values in square brackets are [Docker secrets](https://docs.docker.com/engine/swarm/secrets/). + +### cloudflared *(production only)* + +You can configure the secure tunnel at [dash.cloudflare.com](https://dash.cloudflare.com/). + +### debezium + +You can see how changes in the database end up in the event stream using `redpanda-console`. + +### debezium-postgres-connector + +You can check the database connector's setup logs using `portainer`. + +### elasticsearch + +You cannot access the search engine via a web interface. + +### geoip + +You cannot access the ip geolocator via a web interface. + +### grafana + +You can access the observation dashboard at [grafana.app.localhost](https://grafana.app.localhost/). + +### jobber + +You cannot access the jobber via a web interface. + +### memcached + +You cannot access the caching system via a web interface. + +### minio + +You can access the s3 console at [minio.app.localhost](https://minio.app.localhost/). +You can access the s3 api service at [s3.app.localhost](https://s3.app.localhost/) if you want to access via cli from outside the stack. + +### portainer + +You can access the container manager's frontend at [portainer.app.localhost](https://portainer.app.localhost/). + +### portainer-agent + +You cannot access the container manager's agent directly. + +### postgraphile + +You can access the GraphQL API for the PostgreSQL database at [postgraphile.app.localhost](https://postgraphile.app.localhost/). + +### postgres + +You can access the database via `adminer`. + +### postgres-backup *(production only)* + +You cannot access the database backup directly. + +### prometheus + +You can access the metrics monitoring at [prometheus.app.localhost](https://prometheus.app.localhost/). + +### reccoom + +You cannot access the recommendation service directly. + +### reccoom_postgres + +You can access reccoom's database via `adminer`. + +### redis + +You cannot access the caching system via a web interface. + +### redpanda + +You can access the event streaming platform's ui as described under `redpanda-console`. + +### redpanda-console + +You can access the event streaming platform's ui at [redpanda.app.localhost](https://redpanda.app.localhost/). + +### sqitch + +You cannot access the database migrations directly. + +### traefik + +You can access the reverse proxy's dashboard at [traefik.app.localhost](https://traefik.app.localhost/). + +### traefik-certs-dumper *(production only)* + +You cannot access the reverse proxy's certificate helper directly. + +### tusd + +You can access the upload service at [tusd.app.localhost](https://tusd.app.localhost/). + +### vibetype + +You can access the main project's frontend at [app.localhost](https://app.localhost/). + +### zammad-backup + +You cannot access the helpdesk backup service via a web interface. + +### zammad-init + +You cannot access the helpdesk initialization service via a web interface. + +### zammad-nginx + +You can access the helpdesk at [zammad.app.localhost](https://zammad.app.localhost/). + +### zammad-railsserver + +You cannot access the helpdesk application server directly. + +### zammad-scheduler + +You cannot access the helpdesk scheduler directly. + +### zammad-websocket + +You cannot access the helpdesk websocket server directly. + diff --git a/NOTES.md b/artifacts/docs/SERVICES_ADDITIONAL.md similarity index 91% rename from NOTES.md rename to artifacts/docs/SERVICES_ADDITIONAL.md index ce1846d5..3ac38388 100644 --- a/NOTES.md +++ b/artifacts/docs/SERVICES_ADDITIONAL.md @@ -1,4 +1,5 @@ # Additional Services + - ## `status` ![production](https://img.shields.io/badge/-production-informational.svg?style=flat-square) [![Website Uptime Monitoring](https://app.statuscake.com/button/index.php?Track=9CFPA32m2n&Days=1000&Design=6)](https://www.statuscake.com) - You can access the status dashboard at [status.vibetype.app](https://status.vibetype.app/) \ No newline at end of file + You can access the status dashboard at [status.vibetype.app](https://status.vibetype.app/) diff --git a/dargstack.env b/dargstack.env deleted file mode 100644 index aff39cd0..00000000 --- a/dargstack.env +++ /dev/null @@ -1 +0,0 @@ -PROJECT_NAME=vibetype \ No newline at end of file diff --git a/dargstack.yaml b/dargstack.yaml new file mode 100644 index 00000000..dd68f610 --- /dev/null +++ b/dargstack.yaml @@ -0,0 +1,47 @@ +# Dargstack configuration file + +# # Stack name — used as Docker stack name and image tag prefix +name: "vibetype" + +# # Source code metadata (for documentation generation) +# source: +# name: "example" +# url: "https://github.com/example/example" + +##### + +# Version: This CLI is compatible with config versions < 1.0.0 +compatibility: ">=4.0.0-0 <5.0.0" + +# Sudo mode — if Docker requires sudo on this machine, set to "always" +# Options: "always", "never", "auto" (default) +sudo: "auto" + +# Behavior configuration +behavior: + build: + # Skip rebuilding images if they already exist + skip: true + prompt: + volume: + # Prompt to remove volumes before deploying (development only) + remove: false # default: true + +# Production environment settings +production: + # Stack domain — used by the public to reach the services + domain: "vibetype.app" + # Git branch for production deployments + branch: "main" + # Tag strategy for production — use "latest" to auto-detect from git tags + tag: "latest" + +# Development environment settings +development: + # Domain used for development deployments (defaults to "app.localhost"). + domain: "app.localhost" + certificate: + # Additional domains for development TLS certificates (beyond the auto-discovered ones). + domains: [] + # - "*.app.localhost" + # - "custom.localhost" \ No newline at end of file diff --git a/package.json b/package.json deleted file mode 100644 index 6ab49f14..00000000 --- a/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "author": "Jonas Thelemann ", - "description": "Dargstack configuration for Vibetype.", - "devDependencies": { - "@commitlint/cli": "20.4.3", - "@commitlint/config-conventional": "20.4.3", - "conventional-changelog-conventionalcommits": "9.3.0", - "dargstack": "3.0.0", - "dargstack_rgen": "0.9.86", - "husky": "9.1.7" - }, - "engines": { - "node": "24" - }, - "license": "GPL-3.0-only", - "name": "@maevsi/stack", - "packageManager": "pnpm@10.30.3", - "private": true, - "repository": "https://github.com/maevsi/stack.git", - "scripts": { - "prepare": "husky && ./src/development/certificates/mkcert.sh" - }, - "type": "module", - "version": "17.0.0-beta.4" -} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml deleted file mode 100644 index 7d4e1034..00000000 --- a/pnpm-lock.yaml +++ /dev/null @@ -1,837 +0,0 @@ -lockfileVersion: '9.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: - devDependencies: - '@commitlint/cli': - specifier: 20.4.3 - version: 20.4.3(@types/node@25.3.5)(typescript@5.9.3) - '@commitlint/config-conventional': - specifier: 20.4.3 - version: 20.4.3 - conventional-changelog-conventionalcommits: - specifier: 9.3.0 - version: 9.3.0 - dargstack: - specifier: 3.0.0 - version: 3.0.0 - dargstack_rgen: - specifier: 0.9.86 - version: 0.9.86 - husky: - specifier: 9.1.7 - version: 9.1.7 - -packages: - - '@babel/code-frame@7.29.0': - resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} - engines: {node: '>=6.9.0'} - - '@babel/helper-validator-identifier@7.28.5': - resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} - engines: {node: '>=6.9.0'} - - '@commitlint/cli@20.4.3': - resolution: {integrity: sha512-Z37EMoDT7+Upg500vlr/vZrgRsb6Xc5JAA3Tv7BYbobnN/ZpqUeZnSLggBg2+1O+NptRDtyujr2DD1CPV2qwhA==} - engines: {node: '>=v18'} - hasBin: true - - '@commitlint/config-conventional@20.4.3': - resolution: {integrity: sha512-9RtLySbYQAs8yEqWEqhSZo9nYhbm57jx7qHXtgRmv/nmeQIjjMcwf6Dl+y5UZcGWgWx435TAYBURONaJIuCjWg==} - engines: {node: '>=v18'} - - '@commitlint/config-validator@20.4.3': - resolution: {integrity: sha512-jCZpZFkcSL3ZEdL5zgUzFRdytv3xPo8iukTe9VA+QGus/BGhpp1xXSVu2B006GLLb2gYUAEGEqv64kTlpZNgmA==} - engines: {node: '>=v18'} - - '@commitlint/ensure@20.4.3': - resolution: {integrity: sha512-WcXGKBNn0wBKpX8VlXgxqedyrLxedIlLBCMvdamLnJFEbUGJ9JZmBVx4vhLV3ZyA8uONGOb+CzW0Y9HDbQ+ONQ==} - engines: {node: '>=v18'} - - '@commitlint/execute-rule@20.0.0': - resolution: {integrity: sha512-xyCoOShoPuPL44gVa+5EdZsBVao/pNzpQhkzq3RdtlFdKZtjWcLlUFQHSWBuhk5utKYykeJPSz2i8ABHQA+ZZw==} - engines: {node: '>=v18'} - - '@commitlint/format@20.4.3': - resolution: {integrity: sha512-UDJVErjLbNghop6j111rsHJYGw6MjCKAi95K0GT2yf4eeiDHy3JDRLWYWEjIaFgO+r+dQSkuqgJ1CdMTtrvHsA==} - engines: {node: '>=v18'} - - '@commitlint/is-ignored@20.4.3': - resolution: {integrity: sha512-W5VQKZ7fdJ1X3Tko+h87YZaqRMGN1KvQKXyCM8xFdxzMIf1KCZgN4uLz3osLB1zsFcVS4ZswHY64LI26/9ACag==} - engines: {node: '>=v18'} - - '@commitlint/lint@20.4.3': - resolution: {integrity: sha512-CYOXL23e+nRKij81+d0+dymtIi7Owl9QzvblJYbEfInON/4MaETNSLFDI74LDu+YJ0ML5HZyw9Vhp9QpckwQ0A==} - engines: {node: '>=v18'} - - '@commitlint/load@20.4.3': - resolution: {integrity: sha512-3cdJOUVP+VcgHa7bhJoWS+Z8mBNXB5aLWMBu7Q7uX8PSeWDzdbrBlR33J1MGGf7r1PZDp+mPPiFktk031PgdRw==} - engines: {node: '>=v18'} - - '@commitlint/message@20.4.3': - resolution: {integrity: sha512-6akwCYrzcrFcTYz9GyUaWlhisY4lmQ3KvrnabmhoeAV8nRH4dXJAh4+EUQ3uArtxxKQkvxJS78hNX2EU3USgxQ==} - engines: {node: '>=v18'} - - '@commitlint/parse@20.4.3': - resolution: {integrity: sha512-hzC3JCo3zs3VkQ833KnGVuWjWIzR72BWZWjQM7tY/7dfKreKAm7fEsy71tIFCRtxf2RtMP2d3RLF1U9yhFSccA==} - engines: {node: '>=v18'} - - '@commitlint/read@20.4.3': - resolution: {integrity: sha512-j42OWv3L31WfnP8WquVjHZRt03w50Y/gEE8FAyih7GQTrIv2+pZ6VZ6pWLD/ml/3PO+RV2SPtRtTp/MvlTb8rQ==} - engines: {node: '>=v18'} - - '@commitlint/resolve-extends@20.4.3': - resolution: {integrity: sha512-QucxcOy+00FhS9s4Uy0OyS5HeUV+hbC6OLqkTSIm6fwMdKva+OEavaCDuLtgd9akZZlsUo//XzSmPP3sLKBPog==} - engines: {node: '>=v18'} - - '@commitlint/rules@20.4.3': - resolution: {integrity: sha512-Yuosd7Grn5qiT7FovngXLyRXTMUbj9PYiSkvUgWK1B5a7+ZvrbWDS7epeUapYNYatCy/KTpPFPbgLUdE+MUrBg==} - engines: {node: '>=v18'} - - '@commitlint/to-lines@20.0.0': - resolution: {integrity: sha512-2l9gmwiCRqZNWgV+pX1X7z4yP0b3ex/86UmUFgoRt672Ez6cAM2lOQeHFRUTuE6sPpi8XBCGnd8Kh3bMoyHwJw==} - engines: {node: '>=v18'} - - '@commitlint/top-level@20.4.3': - resolution: {integrity: sha512-qD9xfP6dFg5jQ3NMrOhG0/w5y3bBUsVGyJvXxdWEwBm8hyx4WOk3kKXw28T5czBYvyeCVJgJJ6aoJZUWDpaacQ==} - engines: {node: '>=v18'} - - '@commitlint/types@20.4.3': - resolution: {integrity: sha512-51OWa1Gi6ODOasPmfJPq6js4pZoomima4XLZZCrkldaH2V5Nb3bVhNXPeT6XV0gubbainSpTw4zi68NqAeCNCg==} - engines: {node: '>=v18'} - - '@simple-libs/stream-utils@1.2.0': - resolution: {integrity: sha512-KxXvfapcixpz6rVEB6HPjOUZT22yN6v0vI0urQSk1L8MlEWPDFCZkhw2xmkyoTGYeFw7tWTZd7e3lVzRZRN/EA==} - engines: {node: '>=18'} - - '@types/node@25.3.5': - resolution: {integrity: sha512-oX8xrhvpiyRCQkG1MFchB09f+cXftgIXb3a7UUa4Y3wpmZPw5tyZGTLWhlESOLq1Rq6oDlc8npVU2/9xiCuXMA==} - - ajv@8.18.0: - resolution: {integrity: sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==} - - ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - - ansi-regex@6.2.2: - resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} - engines: {node: '>=12'} - - ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - - ansi-styles@6.2.3: - resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} - engines: {node: '>=12'} - - argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - - array-ify@1.0.0: - resolution: {integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==} - - callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - - cliui@8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} - engines: {node: '>=12'} - - cliui@9.0.1: - resolution: {integrity: sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==} - engines: {node: '>=20'} - - color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - - color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - - compare-func@2.0.0: - resolution: {integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==} - - conventional-changelog-angular@8.3.0: - resolution: {integrity: sha512-DOuBwYSqWzfwuRByY9O4oOIvDlkUCTDzfbOgcSbkY+imXXj+4tmrEFao3K+FxemClYfYnZzsvudbwrhje9VHDA==} - engines: {node: '>=18'} - - conventional-changelog-conventionalcommits@9.3.0: - resolution: {integrity: sha512-kYFx6gAyjSIMwNtASkI3ZE99U1fuVDJr0yTYgVy+I2QG46zNZfl2her+0+eoviG82c5WQvW1jMt1eOQTeJLodA==} - engines: {node: '>=18'} - - conventional-commits-parser@6.3.0: - resolution: {integrity: sha512-RfOq/Cqy9xV9bOA8N+ZH6DlrDR+5S3Mi0B5kACEjESpE+AviIpAptx9a9cFpWCCvgRtWT+0BbUw+e1BZfts9jg==} - engines: {node: '>=18'} - hasBin: true - - cosmiconfig-typescript-loader@6.2.0: - resolution: {integrity: sha512-GEN39v7TgdxgIoNcdkRE3uiAzQt3UXLyHbRHD6YoL048XAeOomyxaP+Hh/+2C6C2wYjxJ2onhJcsQp+L4YEkVQ==} - engines: {node: '>=v18'} - peerDependencies: - '@types/node': '*' - cosmiconfig: '>=9' - typescript: '>=5' - - cosmiconfig@9.0.1: - resolution: {integrity: sha512-hr4ihw+DBqcvrsEDioRO31Z17x71pUYoNe/4h6Z0wB72p7MU7/9gH8Q3s12NFhHPfYBBOV3qyfUxmr/Yn3shnQ==} - engines: {node: '>=14'} - peerDependencies: - typescript: '>=4.9.5' - peerDependenciesMeta: - typescript: - optional: true - - dargs@8.1.0: - resolution: {integrity: sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==} - engines: {node: '>=12'} - - dargstack@3.0.0: - resolution: {integrity: sha512-hJn6NSEDiDvkH+3THlnLGHyvxagrm+t7f1snRSNER0u5A+manl2Wy1A7oFq6tWGtBIj0DDVoT0llpMlh8R9xQw==} - engines: {node: '24'} - - dargstack_rgen@0.9.86: - resolution: {integrity: sha512-3pwqv3r7BqaSu8LWYyzA8S5OP4EAxBHXhAEHywEGPXiSbl9j17KAhGHIUaFmGX5GPeUWF0B+N5Uh5nmlMkD/Vg==} - engines: {node: '24'} - hasBin: true - - deepmerge@4.3.1: - resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} - engines: {node: '>=0.10.0'} - - diff@8.0.3: - resolution: {integrity: sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ==} - engines: {node: '>=0.3.1'} - - dot-prop@5.3.0: - resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==} - engines: {node: '>=8'} - - emoji-regex@10.6.0: - resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} - - emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - - env-paths@2.2.1: - resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} - engines: {node: '>=6'} - - error-ex@1.3.4: - resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} - - escalade@3.2.0: - resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} - engines: {node: '>=6'} - - fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - - fast-uri@3.1.0: - resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} - - get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - - get-east-asian-width@1.5.0: - resolution: {integrity: sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==} - engines: {node: '>=18'} - - git-raw-commits@4.0.0: - resolution: {integrity: sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ==} - engines: {node: '>=16'} - deprecated: This package is no longer maintained. For the JavaScript API, please use @conventional-changelog/git-client instead. - hasBin: true - - global-directory@4.0.1: - resolution: {integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==} - engines: {node: '>=18'} - - husky@9.1.7: - resolution: {integrity: sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==} - engines: {node: '>=18'} - hasBin: true - - import-fresh@3.3.1: - resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} - engines: {node: '>=6'} - - import-meta-resolve@4.2.0: - resolution: {integrity: sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==} - - indento@1.1.14: - resolution: {integrity: sha512-K4cK97v4M/ucCAbe3LUpg994folYL0WnEiCFxHXAIowKLbBb/Ahiazkz3Ao5gRar4i9pDr3imcpq4suOu0FbNw==} - - ini@4.1.1: - resolution: {integrity: sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - is-arrayish@0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - - is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - - is-obj@2.0.0: - resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} - engines: {node: '>=8'} - - is-plain-obj@4.1.0: - resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} - engines: {node: '>=12'} - - jiti@2.6.1: - resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} - hasBin: true - - js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - - js-yaml@4.1.1: - resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} - hasBin: true - - json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - - json-schema-traverse@1.0.0: - resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} - - json2md@2.0.3: - resolution: {integrity: sha512-ZPzh6Djvqz8grJMxKllfCHo0p+p7BsbZ1J95KcCJgvvfdoy7myuKrrkUp80Kpy+wGauykC0dYljLqLY0kENaOw==} - - lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - - lodash.camelcase@4.3.0: - resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} - - lodash.kebabcase@4.1.1: - resolution: {integrity: sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==} - - lodash.mergewith@4.6.2: - resolution: {integrity: sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==} - - lodash.snakecase@4.1.1: - resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==} - - lodash.startcase@4.4.0: - resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} - - lodash.upperfirst@4.3.1: - resolution: {integrity: sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==} - - meow@12.1.1: - resolution: {integrity: sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==} - engines: {node: '>=16.10'} - - meow@13.2.0: - resolution: {integrity: sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==} - engines: {node: '>=18'} - - minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - - parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} - - parse-json@5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} - - picocolors@1.1.1: - resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - - require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - - require-from-string@2.0.2: - resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} - engines: {node: '>=0.10.0'} - - resolve-from@4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} - - resolve-from@5.0.0: - resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} - engines: {node: '>=8'} - - semver@7.7.4: - resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} - engines: {node: '>=10'} - hasBin: true - - split2@4.2.0: - resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} - engines: {node: '>= 10.x'} - - string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - - string-width@7.2.0: - resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} - engines: {node: '>=18'} - - strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - - strip-ansi@7.2.0: - resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} - engines: {node: '>=12'} - - tinyexec@1.0.2: - resolution: {integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==} - engines: {node: '>=18'} - - typescript@5.9.3: - resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} - engines: {node: '>=14.17'} - hasBin: true - - undici-types@7.18.2: - resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} - - wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} - - wrap-ansi@9.0.2: - resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} - engines: {node: '>=18'} - - y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - - yaml@2.8.2: - resolution: {integrity: sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==} - engines: {node: '>= 14.6'} - hasBin: true - - yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} - - yargs-parser@22.0.0: - resolution: {integrity: sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==} - engines: {node: ^20.19.0 || ^22.12.0 || >=23} - - yargs@17.7.2: - resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} - engines: {node: '>=12'} - - yargs@18.0.0: - resolution: {integrity: sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==} - engines: {node: ^20.19.0 || ^22.12.0 || >=23} - -snapshots: - - '@babel/code-frame@7.29.0': - dependencies: - '@babel/helper-validator-identifier': 7.28.5 - js-tokens: 4.0.0 - picocolors: 1.1.1 - - '@babel/helper-validator-identifier@7.28.5': {} - - '@commitlint/cli@20.4.3(@types/node@25.3.5)(typescript@5.9.3)': - dependencies: - '@commitlint/format': 20.4.3 - '@commitlint/lint': 20.4.3 - '@commitlint/load': 20.4.3(@types/node@25.3.5)(typescript@5.9.3) - '@commitlint/read': 20.4.3 - '@commitlint/types': 20.4.3 - tinyexec: 1.0.2 - yargs: 17.7.2 - transitivePeerDependencies: - - '@types/node' - - typescript - - '@commitlint/config-conventional@20.4.3': - dependencies: - '@commitlint/types': 20.4.3 - conventional-changelog-conventionalcommits: 9.3.0 - - '@commitlint/config-validator@20.4.3': - dependencies: - '@commitlint/types': 20.4.3 - ajv: 8.18.0 - - '@commitlint/ensure@20.4.3': - dependencies: - '@commitlint/types': 20.4.3 - lodash.camelcase: 4.3.0 - lodash.kebabcase: 4.1.1 - lodash.snakecase: 4.1.1 - lodash.startcase: 4.4.0 - lodash.upperfirst: 4.3.1 - - '@commitlint/execute-rule@20.0.0': {} - - '@commitlint/format@20.4.3': - dependencies: - '@commitlint/types': 20.4.3 - picocolors: 1.1.1 - - '@commitlint/is-ignored@20.4.3': - dependencies: - '@commitlint/types': 20.4.3 - semver: 7.7.4 - - '@commitlint/lint@20.4.3': - dependencies: - '@commitlint/is-ignored': 20.4.3 - '@commitlint/parse': 20.4.3 - '@commitlint/rules': 20.4.3 - '@commitlint/types': 20.4.3 - - '@commitlint/load@20.4.3(@types/node@25.3.5)(typescript@5.9.3)': - dependencies: - '@commitlint/config-validator': 20.4.3 - '@commitlint/execute-rule': 20.0.0 - '@commitlint/resolve-extends': 20.4.3 - '@commitlint/types': 20.4.3 - cosmiconfig: 9.0.1(typescript@5.9.3) - cosmiconfig-typescript-loader: 6.2.0(@types/node@25.3.5)(cosmiconfig@9.0.1(typescript@5.9.3))(typescript@5.9.3) - is-plain-obj: 4.1.0 - lodash.mergewith: 4.6.2 - picocolors: 1.1.1 - transitivePeerDependencies: - - '@types/node' - - typescript - - '@commitlint/message@20.4.3': {} - - '@commitlint/parse@20.4.3': - dependencies: - '@commitlint/types': 20.4.3 - conventional-changelog-angular: 8.3.0 - conventional-commits-parser: 6.3.0 - - '@commitlint/read@20.4.3': - dependencies: - '@commitlint/top-level': 20.4.3 - '@commitlint/types': 20.4.3 - git-raw-commits: 4.0.0 - minimist: 1.2.8 - tinyexec: 1.0.2 - - '@commitlint/resolve-extends@20.4.3': - dependencies: - '@commitlint/config-validator': 20.4.3 - '@commitlint/types': 20.4.3 - global-directory: 4.0.1 - import-meta-resolve: 4.2.0 - lodash.mergewith: 4.6.2 - resolve-from: 5.0.0 - - '@commitlint/rules@20.4.3': - dependencies: - '@commitlint/ensure': 20.4.3 - '@commitlint/message': 20.4.3 - '@commitlint/to-lines': 20.0.0 - '@commitlint/types': 20.4.3 - - '@commitlint/to-lines@20.0.0': {} - - '@commitlint/top-level@20.4.3': - dependencies: - escalade: 3.2.0 - - '@commitlint/types@20.4.3': - dependencies: - conventional-commits-parser: 6.3.0 - picocolors: 1.1.1 - - '@simple-libs/stream-utils@1.2.0': {} - - '@types/node@25.3.5': - dependencies: - undici-types: 7.18.2 - - ajv@8.18.0: - dependencies: - fast-deep-equal: 3.1.3 - fast-uri: 3.1.0 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - - ansi-regex@5.0.1: {} - - ansi-regex@6.2.2: {} - - ansi-styles@4.3.0: - dependencies: - color-convert: 2.0.1 - - ansi-styles@6.2.3: {} - - argparse@2.0.1: {} - - array-ify@1.0.0: {} - - callsites@3.1.0: {} - - cliui@8.0.1: - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - - cliui@9.0.1: - dependencies: - string-width: 7.2.0 - strip-ansi: 7.2.0 - wrap-ansi: 9.0.2 - - color-convert@2.0.1: - dependencies: - color-name: 1.1.4 - - color-name@1.1.4: {} - - compare-func@2.0.0: - dependencies: - array-ify: 1.0.0 - dot-prop: 5.3.0 - - conventional-changelog-angular@8.3.0: - dependencies: - compare-func: 2.0.0 - - conventional-changelog-conventionalcommits@9.3.0: - dependencies: - compare-func: 2.0.0 - - conventional-commits-parser@6.3.0: - dependencies: - '@simple-libs/stream-utils': 1.2.0 - meow: 13.2.0 - - cosmiconfig-typescript-loader@6.2.0(@types/node@25.3.5)(cosmiconfig@9.0.1(typescript@5.9.3))(typescript@5.9.3): - dependencies: - '@types/node': 25.3.5 - cosmiconfig: 9.0.1(typescript@5.9.3) - jiti: 2.6.1 - typescript: 5.9.3 - - cosmiconfig@9.0.1(typescript@5.9.3): - dependencies: - env-paths: 2.2.1 - import-fresh: 3.3.1 - js-yaml: 4.1.1 - parse-json: 5.2.0 - optionalDependencies: - typescript: 5.9.3 - - dargs@8.1.0: {} - - dargstack@3.0.0: {} - - dargstack_rgen@0.9.86: - dependencies: - deepmerge: 4.3.1 - diff: 8.0.3 - json2md: 2.0.3 - yaml: 2.8.2 - yargs: 18.0.0 - - deepmerge@4.3.1: {} - - diff@8.0.3: {} - - dot-prop@5.3.0: - dependencies: - is-obj: 2.0.0 - - emoji-regex@10.6.0: {} - - emoji-regex@8.0.0: {} - - env-paths@2.2.1: {} - - error-ex@1.3.4: - dependencies: - is-arrayish: 0.2.1 - - escalade@3.2.0: {} - - fast-deep-equal@3.1.3: {} - - fast-uri@3.1.0: {} - - get-caller-file@2.0.5: {} - - get-east-asian-width@1.5.0: {} - - git-raw-commits@4.0.0: - dependencies: - dargs: 8.1.0 - meow: 12.1.1 - split2: 4.2.0 - - global-directory@4.0.1: - dependencies: - ini: 4.1.1 - - husky@9.1.7: {} - - import-fresh@3.3.1: - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - - import-meta-resolve@4.2.0: {} - - indento@1.1.14: {} - - ini@4.1.1: {} - - is-arrayish@0.2.1: {} - - is-fullwidth-code-point@3.0.0: {} - - is-obj@2.0.0: {} - - is-plain-obj@4.1.0: {} - - jiti@2.6.1: {} - - js-tokens@4.0.0: {} - - js-yaml@4.1.1: - dependencies: - argparse: 2.0.1 - - json-parse-even-better-errors@2.3.1: {} - - json-schema-traverse@1.0.0: {} - - json2md@2.0.3: - dependencies: - indento: 1.1.14 - - lines-and-columns@1.2.4: {} - - lodash.camelcase@4.3.0: {} - - lodash.kebabcase@4.1.1: {} - - lodash.mergewith@4.6.2: {} - - lodash.snakecase@4.1.1: {} - - lodash.startcase@4.4.0: {} - - lodash.upperfirst@4.3.1: {} - - meow@12.1.1: {} - - meow@13.2.0: {} - - minimist@1.2.8: {} - - parent-module@1.0.1: - dependencies: - callsites: 3.1.0 - - parse-json@5.2.0: - dependencies: - '@babel/code-frame': 7.29.0 - error-ex: 1.3.4 - json-parse-even-better-errors: 2.3.1 - lines-and-columns: 1.2.4 - - picocolors@1.1.1: {} - - require-directory@2.1.1: {} - - require-from-string@2.0.2: {} - - resolve-from@4.0.0: {} - - resolve-from@5.0.0: {} - - semver@7.7.4: {} - - split2@4.2.0: {} - - string-width@4.2.3: - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - - string-width@7.2.0: - dependencies: - emoji-regex: 10.6.0 - get-east-asian-width: 1.5.0 - strip-ansi: 7.2.0 - - strip-ansi@6.0.1: - dependencies: - ansi-regex: 5.0.1 - - strip-ansi@7.2.0: - dependencies: - ansi-regex: 6.2.2 - - tinyexec@1.0.2: {} - - typescript@5.9.3: {} - - undici-types@7.18.2: {} - - wrap-ansi@7.0.0: - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - - wrap-ansi@9.0.2: - dependencies: - ansi-styles: 6.2.3 - string-width: 7.2.0 - strip-ansi: 7.2.0 - - y18n@5.0.8: {} - - yaml@2.8.2: {} - - yargs-parser@21.1.1: {} - - yargs-parser@22.0.0: {} - - yargs@17.7.2: - dependencies: - cliui: 8.0.1 - escalade: 3.2.0 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 21.1.1 - - yargs@18.0.0: - dependencies: - cliui: 9.0.1 - escalade: 3.2.0 - get-caller-file: 2.0.5 - string-width: 7.2.0 - y18n: 5.0.8 - yargs-parser: 22.0.0 diff --git a/src/.gitignore b/src/.gitignore deleted file mode 100644 index 71cda2dc..00000000 --- a/src/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -**/backups/*/** -**/production/secrets/**/*.secret -*.crt -*.csr -*.env -*.key -!**/README.md -!**/*.template -production/stack.yml diff --git a/src/development/adminer/compose.yaml b/src/development/adminer/compose.yaml new file mode 100644 index 00000000..8f9a6eee --- /dev/null +++ b/src/development/adminer/compose.yaml @@ -0,0 +1,28 @@ +services: + adminer: + # You can access the database's frontend at [adminer.app.localhost](https://adminer.app.localhost/). + # This information is required for login: + # + # | | | + # | -------- | ------------------- | + # | System | PostgreSQL | + # | Server | postgres | + # | Username | [postgres-user] | + # | Password | [postgres-password] | + # | Database | [postgres-db] | + # + # Values in square brackets are [Docker secrets](https://docs.docker.com/engine/swarm/secrets/). + deploy: + labels: + - dargstack.profiles=default + - traefik.enable=true + - traefik.http.routers.adminer.entryPoints=web + - traefik.http.routers.adminer.middlewares=redirectscheme # dargstack:dev-only + - traefik.http.routers.adminer.rule=Host(`adminer.${STACK_DOMAIN}`) + - traefik.http.routers.adminer-secure.entryPoints=web-secure + - traefik.http.routers.adminer-secure.rule=Host(`adminer.${STACK_DOMAIN}`) + - traefik.http.routers.adminer-secure.tls.options=mintls13@file # dargstack:dev-only + - traefik.http.services.adminer.loadbalancer.server.port=8080 + image: adminer:5.4.2-standalone + volumes: + - ./configurations/adminer.css:/var/www/html/adminer.css:ro diff --git a/src/development/adminer/configurations/adminer.css b/src/development/adminer/configurations/adminer.css new file mode 100755 index 00000000..3da66c8c --- /dev/null +++ b/src/development/adminer/configurations/adminer.css @@ -0,0 +1,7 @@ +a { + color: blue; +} + +a:visited { + color: blue; +} diff --git a/src/development/certificates/mkcert.sh b/src/development/certificates/mkcert.sh deleted file mode 100755 index 25c841c4..00000000 --- a/src/development/certificates/mkcert.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/sh -THIS=$(dirname "$(readlink -f "$0")") - -create() { - NAME="$1" - shift - CONTENT=$* - - path="$THIS/$NAME" - certfile="$path.crt" - keyfile="$path.key" - - if [ "$CONTENT" != "" ]; then - # shellcheck disable=SC2086 - mkcert \ - -cert-file "$certfile" \ - -ecdsa \ - -key-file "$keyfile" $CONTENT - fi - - cat "$(mkcert -CAROOT)/rootCA.pem" >> "$certfile" -} - -echo "key crt" | tr ' ' '\n' | while read -r glob; do - if test -n "$(find "$THIS" -maxdepth 1 -name "*.$glob" -print -quit)"; then - rm "$THIS"/*."$glob" - fi -done - -create "root" -create "traefik" \ - `# adminer` "adminer.app.localhost" \ - `# grafana` "grafana.app.localhost" \ - `# minio` "minio.app.localhost" \ - `# portainer` "portainer.app.localhost" \ - `# postgraphile` "postgraphile.app.localhost" \ - `# prometheus` "prometheus.app.localhost" \ - `# reccoom` "reccoom.app.localhost" \ - `# redpanda` "redpanda.app.localhost" \ - `# traefik` "traefik.app.localhost" \ - `# tusd` "tusd.app.localhost" \ - `# vibetype` "app.localhost" "www.app.localhost" "127.0.0.1" "0.0.0.0" \ - `# zammad` "zammad.app.localhost" \ No newline at end of file diff --git a/src/development/compose.yaml b/src/development/compose.yaml new file mode 100644 index 00000000..38b1f0ed --- /dev/null +++ b/src/development/compose.yaml @@ -0,0 +1,5 @@ +version: "3.7" +volumes: + pnpm-data: + # The node package manager's data. + {} diff --git a/src/development/configurations/traefik/dynamic.yml b/src/development/configurations/traefik/dynamic.yml deleted file mode 100644 index 5fdce1e4..00000000 --- a/src/development/configurations/traefik/dynamic.yml +++ /dev/null @@ -1,7 +0,0 @@ -tls: - certificates: - - certFile: /etc/traefik/acme/traefik.crt - keyFile: /etc/traefik/acme/traefik.key - options: - mintls13: - minVersion: VersionTLS13 \ No newline at end of file diff --git a/src/development/debezium/compose.yaml b/src/development/debezium/compose.yaml new file mode 100644 index 00000000..261a497b --- /dev/null +++ b/src/development/debezium/compose.yaml @@ -0,0 +1,49 @@ +services: + debezium: + # You can see how changes in the database end up in the event stream using `redpanda-console`. + deploy: + labels: + - dargstack.profiles=event-streaming + environment: + BOOTSTRAP_SERVERS: redpanda:9092 + CONFIG_STORAGE_TOPIC: connect_configs + GROUP_ID: 1 + OFFSET_STORAGE_TOPIC: connect_offsets + STATUS_STORAGE_TOPIC: connect_statuses + # healthcheck: + # test: ["CMD", "curl", "--fail", "--silent", "--show-error", "http://localhost:8083/connectors"] + # interval: 30s + # timeout: 10s + # retries: 3 + # start_period: 20s + image: quay.io/debezium/connect:3.5 + volumes: + - debezium-kafka-configuration:/kafka/config + - debezium-kafka-data:/kafka/data + - debezium-kafka-logs:/kafka/logs + debezium-postgres-connector: + # You can check the database connector's setup logs using `portainer`. + command: /entrypoint.sh + deploy: + labels: + - dargstack.profiles=event-streaming + restart_policy: + condition: on-failure + entrypoint: sh + image: curlimages/curl:8.18.0 + secrets: + - postgres-db + - postgres-password + - postgres-user + volumes: + - ./configurations/entrypoint.sh:/entrypoint.sh:ro +volumes: + debezium-kafka-configuration: + # The change data capture's configuration. + {} + debezium-kafka-data: + # The change data capture's data. + {} + debezium-kafka-logs: + # The change data capture's logs. + {} diff --git a/src/production/configurations/debezium-postgres-connector/entrypoint.sh b/src/development/debezium/configurations/entrypoint.sh similarity index 91% rename from src/production/configurations/debezium-postgres-connector/entrypoint.sh rename to src/development/debezium/configurations/entrypoint.sh index 5130d89f..66a731e2 100755 --- a/src/production/configurations/debezium-postgres-connector/entrypoint.sh +++ b/src/development/debezium/configurations/entrypoint.sh @@ -2,9 +2,9 @@ CONNECTOR_NAME="postgres-connector" DEBEZIUM_URL="http://debezium:8083/connectors" -POSTGRES_DB=$(cat /run/secrets/postgres_db) -POSTGRES_PASSWORD=$(cat /run/secrets/postgres_password) -POSTGRES_USER=$(cat /run/secrets/postgres_user) +POSTGRES_DB=$(cat /run/secrets/postgres-db) +POSTGRES_PASSWORD=$(cat /run/secrets/postgres-password) +POSTGRES_USER=$(cat /run/secrets/postgres-user) # Wait for Debezium to be healthy (REST API ready) echo "Waiting for Debezium to be ready..." diff --git a/src/development/elasticsearch/compose.yaml b/src/development/elasticsearch/compose.yaml new file mode 100644 index 00000000..85bb290b --- /dev/null +++ b/src/development/elasticsearch/compose.yaml @@ -0,0 +1,53 @@ +secrets: + elasticsearch-keystore-password: + # The search engine's password for the keystore. + file: ../../../artifacts/secrets/elasticsearch-keystore-password.secret + elasticsearch-password: + # The search engine's password for the default user. + file: ../../../artifacts/secrets/elasticsearch-password.secret +services: + elasticsearch: + # You cannot access the search engine via a web interface. + deploy: + labels: + - dargstack.profiles=zammad + environment: + bootstrap.memory_lock: "true" + discovery.type: single-node + ELASTIC_PASSWORD_FILE: /run/secrets/elasticsearch-password + ES_JAVA_OPTS: -Xms1g -Xmx1g + KEYSTORE_PASSWORD_FILE: /run/secrets/elasticsearch-keystore-password + network.publish_host: elasticsearch + image: elasticsearch:8.19.12 + secrets: + - source: elasticsearch-keystore-password + uid: "1000" + gid: "1000" + mode: 0o400 + - source: elasticsearch-password + uid: "1000" + gid: "1000" + mode: 0o400 + ulimits: + nofile: + soft: 65535 + hard: 65535 + memlock: + soft: -1 + hard: -1 + volumes: + - elasticsearch-configuration:/usr/share/elasticsearch/config + - elasticsearch-data:/usr/share/elasticsearch/data +volumes: + elasticsearch-configuration: + # The search engine's configuration. + {} + elasticsearch-data: + # The search engine's data. + {} +x-dargstack: + secrets: + elasticsearch-keystore-password: + type: random_string + elasticsearch-password: + type: random_string diff --git a/src/development/geoip/compose.yaml b/src/development/geoip/compose.yaml new file mode 100644 index 00000000..a03531ab --- /dev/null +++ b/src/development/geoip/compose.yaml @@ -0,0 +1,4 @@ +services: + geoip: + # You cannot access the ip geolocator via a web interface. + image: ghcr.io/observabilitystack/geoip-api:2026-02 diff --git a/src/development/grafana/compose.yaml b/src/development/grafana/compose.yaml new file mode 100644 index 00000000..2086f442 --- /dev/null +++ b/src/development/grafana/compose.yaml @@ -0,0 +1,65 @@ +secrets: + grafana-admin-email: + # The observation dashboard's admin email. + file: ../../../artifacts/secrets/grafana-admin-email.secret + grafana-admin-password: + # The observation dashboard's admin password. + file: ../../../artifacts/secrets/grafana-admin-password.secret + grafana-admin-user: + # The observation dashboard's admin user. + file: ../../../artifacts/secrets/grafana-admin-user.secret + grafana-discord-webhook: + # The observation dashboard's contact point for Discord. + file: ../../../artifacts/secrets/grafana-discord-webhook.secret +services: + grafana: + # You can access the observation dashboard at [grafana.app.localhost](https://grafana.app.localhost/). + deploy: + labels: + - dargstack.profiles=analytics + - traefik.enable=true + - traefik.http.routers.grafana.entryPoints=web + - traefik.http.routers.grafana.middlewares=redirectscheme # dargstack:dev-only + - traefik.http.routers.grafana.rule=Host(`grafana.${STACK_DOMAIN}`) + - traefik.http.routers.grafana-secure.entryPoints=web-secure + - traefik.http.routers.grafana-secure.rule=Host(`grafana.${STACK_DOMAIN}`) + - traefik.http.routers.grafana-secure.tls.options=mintls13@file # dargstack:dev-only + - traefik.http.services.grafana.loadbalancer.server.port=3000 + environment: + GF_DATABASE_HOST: postgres:5432 + GF_DATABASE_PASSWORD__FILE: /run/secrets/postgres-role-service-grafana-password + GF_DATABASE_TYPE: postgres + GF_DATABASE_USER__FILE: /run/secrets/postgres-role-service-grafana-username + GF_SECURITY_ADMIN_EMAIL__FILE: /run/secrets/grafana-admin-email + GF_SECURITY_ADMIN_PASSWORD__FILE: /run/secrets/grafana-admin-password + GF_SECURITY_ADMIN_USER__FILE: /run/secrets/grafana-admin-user + GF_SERVER_ROOT_URL: https://grafana.${STACK_DOMAIN}/ + image: grafana/grafana:12.4.1 + secrets: + - grafana-admin-email + - grafana-admin-password + - grafana-admin-user + - grafana-discord-webhook + - postgres-db + - postgres-role-service-grafana-password + - postgres-role-service-grafana-username + volumes: + - ./configurations/dashboards:/var/lib/grafana/dashboards:ro + - ./configurations/provisioning:/etc/grafana/provisioning:ro + - grafana-data:/var/lib/grafana +volumes: + grafana-data: + # The observation dashboard's data. + {} +x-dargstack: + secrets: + grafana-admin-email: + insecure_default: admin@localhost + type: insecure_default + grafana-admin-password: + type: random_string + grafana-admin-user: + type: word + grafana-discord-webhook: + hint: https://discord.com/api/webhooks// + type: third_party diff --git a/src/production/configurations/grafana/dashboards/Infrastructure/Advanced/grafana.json b/src/development/grafana/configurations/dashboards/Infrastructure/Advanced/grafana.json similarity index 100% rename from src/production/configurations/grafana/dashboards/Infrastructure/Advanced/grafana.json rename to src/development/grafana/configurations/dashboards/Infrastructure/Advanced/grafana.json diff --git a/src/production/configurations/grafana/dashboards/Infrastructure/Advanced/prometheus-2.0.json b/src/development/grafana/configurations/dashboards/Infrastructure/Advanced/prometheus-2.0.json similarity index 100% rename from src/production/configurations/grafana/dashboards/Infrastructure/Advanced/prometheus-2.0.json rename to src/development/grafana/configurations/dashboards/Infrastructure/Advanced/prometheus-2.0.json diff --git a/src/production/configurations/grafana/dashboards/Infrastructure/operations.json b/src/development/grafana/configurations/dashboards/Infrastructure/operations.json similarity index 100% rename from src/production/configurations/grafana/dashboards/Infrastructure/operations.json rename to src/development/grafana/configurations/dashboards/Infrastructure/operations.json diff --git a/src/production/configurations/grafana/dashboards/Infrastructure/redpanda.json b/src/development/grafana/configurations/dashboards/Infrastructure/redpanda.json similarity index 100% rename from src/production/configurations/grafana/dashboards/Infrastructure/redpanda.json rename to src/development/grafana/configurations/dashboards/Infrastructure/redpanda.json diff --git a/src/production/configurations/grafana/dashboards/Management/kpis.json b/src/development/grafana/configurations/dashboards/Management/kpis.json similarity index 100% rename from src/production/configurations/grafana/dashboards/Management/kpis.json rename to src/development/grafana/configurations/dashboards/Management/kpis.json diff --git a/src/production/configurations/grafana/provisioning/alerting/alert-notifications-pending.yaml b/src/development/grafana/configurations/provisioning/alerting/alert-notifications-pending.yaml similarity index 100% rename from src/production/configurations/grafana/provisioning/alerting/alert-notifications-pending.yaml rename to src/development/grafana/configurations/provisioning/alerting/alert-notifications-pending.yaml diff --git a/src/production/configurations/grafana/provisioning/alerting/contact-points.yaml b/src/development/grafana/configurations/provisioning/alerting/contact-points.yaml similarity index 94% rename from src/production/configurations/grafana/provisioning/alerting/contact-points.yaml rename to src/development/grafana/configurations/provisioning/alerting/contact-points.yaml index cf88e5ce..832c0958 100644 --- a/src/production/configurations/grafana/provisioning/alerting/contact-points.yaml +++ b/src/development/grafana/configurations/provisioning/alerting/contact-points.yaml @@ -1,7 +1,7 @@ apiVersion: 1 contactPoints: - orgId: 1 - name: 'Discord' + name: Discord receivers: - uid: aen6t8xrd6pkwb type: discord @@ -25,6 +25,6 @@ contactPoints: {{ template "__alert_details" .Alerts.Resolved }}{{ end }}{{ end }}{{ template "default.message_custom" . }} <@&1377144332154572831> - url: $__file{/run/secrets/grafana_discord_webhook} + url: $__file{/run/secrets/grafana-discord-webhook} use_discord_username: false disableResolveMessage: false diff --git a/src/production/configurations/grafana/provisioning/dashboards/file.yml b/src/development/grafana/configurations/provisioning/dashboards/file.yml similarity index 89% rename from src/production/configurations/grafana/provisioning/dashboards/file.yml rename to src/development/grafana/configurations/provisioning/dashboards/file.yml index 7129ad74..c23fbd8b 100644 --- a/src/production/configurations/grafana/provisioning/dashboards/file.yml +++ b/src/development/grafana/configurations/provisioning/dashboards/file.yml @@ -2,13 +2,13 @@ apiVersion: 1 providers: # an unique provider name. Required - - name: 'File' + - name: "File" # Org id. Default to 1 orgId: 1 # name of the dashboard folder. - folder: '' + folder: "" # folder UID. will be automatically generated if not specified - folderUid: '' + folderUid: "" # provider type. Default to 'file' type: file # disable dashboard deletion @@ -21,4 +21,4 @@ providers: # path to dashboard files on disk. Required when using the 'file' type path: /var/lib/grafana/dashboards # use folder names from filesystem to create folders in Grafana - foldersFromFilesStructure: true \ No newline at end of file + foldersFromFilesStructure: true diff --git a/src/development/grafana/configurations/provisioning/datasources/postgres.yaml b/src/development/grafana/configurations/provisioning/datasources/postgres.yaml new file mode 100644 index 00000000..9d53b3fc --- /dev/null +++ b/src/development/grafana/configurations/provisioning/datasources/postgres.yaml @@ -0,0 +1,14 @@ +apiVersion: 1 + +datasources: + - access: proxy + jsonData: + database: $__file{/run/secrets/postgres-db} + postgresVersion: 1500 + sslmode: disable + name: PostgreSQL + secureJsonData: + password: $__file{/run/secrets/postgres-role-service-grafana-password} + type: grafana-postgresql-datasource + url: postgres:5432 + user: $__file{/run/secrets/postgres-role-service-grafana-username} diff --git a/src/production/configurations/grafana/provisioning/datasources/prometheus.yaml b/src/development/grafana/configurations/provisioning/datasources/prometheus.yaml similarity index 100% rename from src/production/configurations/grafana/provisioning/datasources/prometheus.yaml rename to src/development/grafana/configurations/provisioning/datasources/prometheus.yaml diff --git a/src/development/jobber/compose.yaml b/src/development/jobber/compose.yaml new file mode 100644 index 00000000..447213f2 --- /dev/null +++ b/src/development/jobber/compose.yaml @@ -0,0 +1,90 @@ +secrets: + jobber-aliases: + # The job scheduler's SMTP client mail alias. + file: ../../../artifacts/secrets/jobber-aliases.secret + jobber-aws-bucket: + # The job scheduler's AWS bucket name. + file: ../../../artifacts/secrets/jobber-aws-bucket.secret + jobber-aws-credentials: + # The job scheduler's AWS credentials. + file: ../../../artifacts/secrets/jobber-aws-credentials.secret + jobber-aws-configuration: + # The job scheduler's AWS configuration. + file: ../../../artifacts/secrets/jobber-aws-configuration.secret + jobber-msmtprc: + # The job scheduler's SMTP client configuration. + file: ../../../artifacts/secrets/jobber-msmtprc.secret +services: + jobber: + # You cannot access the jobber via a web interface. + environment: + AWS_SHARED_CREDENTIALS_FILE: /run/secrets/jobber-aws-credentials + image: ghcr.io/dargmuesli/jobber-aws-msmtp:1.3.0 + secrets: + - source: jobber-aliases + target: /etc/aliases + - jobber-aws-bucket + - jobber-aws-credentials + - source: jobber-aws-configuration + target: /home/jobberuser/.aws/config + - source: jobber-msmtprc + target: /etc/msmtprc + volumes: + - ./configurations/sinks:/srv/sinks:ro + - ./configurations/.jobber:/home/jobberuser/.jobber:ro +x-dargstack: + secrets: + jobber-aliases: + type: insecure_default + insecure_default: "default: mail@localhost" + jobber-aws-bucket: + type: word + jobber-aws-credentials: + type: insecure_default + insecure_default: | + [default] + aws_access_key_id = s3user + aws_secret_access_key = s3password + jobber-aws-configuration: + type: template + template: | + [default] + region = + + s3 = + endpoint_url = + signature_version = s3v4 + max_concurrent_requests = 100 + max_queue_size = 1000 + multipart_threshold = 50MB + # Edit the multipart_chunksize value according to the file sizes that you want to upload. The present configuration allows to upload files up to 10 GB (100 requests * 10MB). For example setting it to 5GB allows you to upload files up to 5TB. + multipart_chunksize = 10MB + s3api = + endpoint_url = + + [plugins] + endpoint = awscli_plugin_endpoint + jobber-msmtprc: + type: template + template: | + # Set default values for all following accounts. + defaults + auth on + tls on + tls_trust_file /etc/ssl/certs/ca-certificates.crt + syslog on + + # + account + host + port + from + user + password + # or + #auth off + #tls off + + # Set a default account + account default : + aliases /etc/aliases diff --git a/src/development/configurations/jobber/.jobber b/src/development/jobber/configurations/.jobber similarity index 76% rename from src/development/configurations/jobber/.jobber rename to src/development/jobber/configurations/.jobber index d9067df7..906ff841 100644 --- a/src/development/configurations/jobber/.jobber +++ b/src/development/jobber/configurations/.jobber @@ -2,7 +2,7 @@ version: 1.4 jobs: DBBackup: - cmd: aws s3 sync /backups s3://$(cat /run/secrets/jobber_aws-bucket)/backups + cmd: aws s3 sync /backups s3://$(cat /run/secrets/jobber-aws-bucket)/backups time: 0 0 0 * notifyOnSuccess: - type: system-email diff --git a/src/production/configurations/jobber/sinks/sentry/error.sh b/src/development/jobber/configurations/sinks/sentry/error.sh similarity index 100% rename from src/production/configurations/jobber/sinks/sentry/error.sh rename to src/development/jobber/configurations/sinks/sentry/error.sh diff --git a/src/production/configurations/jobber/sinks/sentry/in-progress.sh b/src/development/jobber/configurations/sinks/sentry/in-progress.sh similarity index 100% rename from src/production/configurations/jobber/sinks/sentry/in-progress.sh rename to src/development/jobber/configurations/sinks/sentry/in-progress.sh diff --git a/src/production/configurations/jobber/sinks/sentry/ok.sh b/src/development/jobber/configurations/sinks/sentry/ok.sh similarity index 100% rename from src/production/configurations/jobber/sinks/sentry/ok.sh rename to src/development/jobber/configurations/sinks/sentry/ok.sh diff --git a/src/development/secrets/jobber/aliases.secret.template b/src/development/jobber/secrets/aliases.secret.template similarity index 100% rename from src/development/secrets/jobber/aliases.secret.template rename to src/development/jobber/secrets/aliases.secret.template diff --git a/src/development/secrets/jobber/aws-bucket.secret.template b/src/development/jobber/secrets/aws-bucket.secret.template similarity index 100% rename from src/development/secrets/jobber/aws-bucket.secret.template rename to src/development/jobber/secrets/aws-bucket.secret.template diff --git a/src/development/secrets/jobber/aws-configuration.secret.template b/src/development/jobber/secrets/aws-configuration.secret.template similarity index 100% rename from src/development/secrets/jobber/aws-configuration.secret.template rename to src/development/jobber/secrets/aws-configuration.secret.template diff --git a/src/development/secrets/jobber/aws-credentials.secret.template b/src/development/jobber/secrets/aws-credentials.secret.template similarity index 100% rename from src/development/secrets/jobber/aws-credentials.secret.template rename to src/development/jobber/secrets/aws-credentials.secret.template diff --git a/src/development/secrets/jobber/msmtprc.secret.template b/src/development/jobber/secrets/msmtprc.secret.template similarity index 100% rename from src/development/secrets/jobber/msmtprc.secret.template rename to src/development/jobber/secrets/msmtprc.secret.template diff --git a/src/development/memcached/compose.yaml b/src/development/memcached/compose.yaml new file mode 100644 index 00000000..23da3818 --- /dev/null +++ b/src/development/memcached/compose.yaml @@ -0,0 +1,8 @@ +services: + memcached: + # You cannot access the caching system via a web interface. + deploy: + labels: + - dargstack.profiles=zammad + image: memcached:1.6.41-alpine + # command: memcached -m 256M diff --git a/src/development/minio/compose.yaml b/src/development/minio/compose.yaml new file mode 100644 index 00000000..afc36ee8 --- /dev/null +++ b/src/development/minio/compose.yaml @@ -0,0 +1,43 @@ +services: + minio: # dargstack:dev-only + # You can access the s3 console at [minio.app.localhost](https://minio.app.localhost/). + # You can access the s3 api service at [s3.app.localhost](https://s3.app.localhost/) if you want to access via cli from outside the stack. + command: server /data --console-address ":9001" # dargstack:dev-only + deploy: # dargstack:dev-only + labels: # dargstack:dev-only + - dargstack.profiles=upload + - traefik.enable=true # dargstack:dev-only + # Minio Console + - traefik.http.routers.minio.entryPoints=web # dargstack:dev-only + - traefik.http.routers.minio.middlewares=redirectscheme # dargstack:dev-only + - traefik.http.routers.minio.rule=Host(`minio.${STACK_DOMAIN}`) # dargstack:dev-only + - traefik.http.routers.minio.service=minio # dargstack:dev-only + - traefik.http.routers.minio-secure.entryPoints=web-secure # dargstack:dev-only + - traefik.http.routers.minio-secure.rule=Host(`minio.${STACK_DOMAIN}`) # dargstack:dev-only + - traefik.http.routers.minio-secure.tls.options=mintls13@file # dargstack:dev-only + - traefik.http.routers.minio-secure.service=minio # dargstack:dev-only + - traefik.http.services.minio.loadbalancer.server.port=9001 # dargstack:dev-only + - traefik.http.services.minio.loadbalancer.passhostheader=true # dargstack:dev-only + # Minio itself + - traefik.http.routers.s3.entryPoints=web # dargstack:dev-only + - traefik.http.routers.s3.middlewares=redirectscheme # dargstack:dev-only + - traefik.http.routers.s3.rule=Host(`s3.${STACK_DOMAIN}`) # dargstack:dev-only + - traefik.http.routers.s3.service=s3 # dargstack:dev-only + - traefik.http.routers.s3-secure.entryPoints=web-secure # dargstack:dev-only + - traefik.http.routers.s3-secure.rule=Host(`s3.${STACK_DOMAIN}`) # dargstack:dev-only + - traefik.http.routers.s3-secure.tls.options=mintls13@file # dargstack:dev-only + - traefik.http.routers.s3-secure.service=s3 # dargstack:dev-only + - traefik.http.services.s3.loadbalancer.server.port=9000 # dargstack:dev-only + - traefik.http.services.s3.loadbalancer.passhostheader=true # dargstack:dev-only + entrypoint: /patched-entrypoint.sh # dargstack:dev-only + image: minio/minio # dargstack:dev-only + volumes: # dargstack:dev-only + - minio-data:/data # dargstack:dev-only + - ./configurations/entrypoint.sh:/patched-entrypoint.sh # dargstack:dev-only + environment: # dargstack:dev-only + MINIO_ROOT_PASSWORD: s3password # dargstack:dev-only + MINIO_ROOT_USER: s3user # dargstack:dev-only +volumes: + minio-data: + # The s3 server's data. + {} diff --git a/src/development/configurations/minio/entrypoint.sh b/src/development/minio/configurations/entrypoint.sh similarity index 100% rename from src/development/configurations/minio/entrypoint.sh rename to src/development/minio/configurations/entrypoint.sh diff --git a/src/development/portainer/compose.yaml b/src/development/portainer/compose.yaml new file mode 100644 index 00000000..6e586ad1 --- /dev/null +++ b/src/development/portainer/compose.yaml @@ -0,0 +1,49 @@ +secrets: + portainer-admin-password: + # The container manager's admin password. + file: ../../../artifacts/secrets/portainer-admin-password.secret +services: + portainer: + # You can access the container manager's frontend at [portainer.app.localhost](https://portainer.app.localhost/). + command: -H tcp://tasks.portainer-agent:9001 --tlsskipverify --admin-password-file '/run/secrets/portainer-admin-password' + deploy: + labels: + - dargstack.profiles=default + - traefik.enable=true + - traefik.http.routers.portainer.entryPoints=web + - traefik.http.routers.portainer.middlewares=redirectscheme # dargstack:dev-only + - traefik.http.routers.portainer.rule=Host(`portainer.${STACK_DOMAIN}`) + - traefik.http.routers.portainer-secure.entryPoints=web-secure + - traefik.http.routers.portainer-secure.rule=Host(`portainer.${STACK_DOMAIN}`) + - traefik.http.routers.portainer-secure.tls.options=mintls13@file # dargstack:dev-only + - traefik.http.services.portainer.loadbalancer.server.port=9000 + placement: + constraints: + - node.role == manager + replicas: 1 + image: portainer/portainer-ce:2.39.0-alpine + secrets: + - portainer-admin-password + volumes: + - portainer-data:/data + portainer-agent: + # You cannot access the container manager's agent directly. + deploy: + labels: + - dargstack.profiles=default + mode: global + placement: + constraints: + - node.platform.os == linux + image: portainer/agent:2.39.0 + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - /var/lib/docker/volumes:/var/lib/docker/volumes +volumes: + portainer-data: + # The container manager's data. + {} +x-dargstack: + secrets: + portainer-admin-password: + type: random_string diff --git a/src/development/secrets/portainer/admin-password.secret.template b/src/development/portainer/secrets/admin-password.secret.template similarity index 100% rename from src/development/secrets/portainer/admin-password.secret.template rename to src/development/portainer/secrets/admin-password.secret.template diff --git a/src/development/postgraphile/compose.yaml b/src/development/postgraphile/compose.yaml new file mode 100644 index 00000000..b8acd655 --- /dev/null +++ b/src/development/postgraphile/compose.yaml @@ -0,0 +1,65 @@ +secrets: + postgraphile-connection: + # The GraphQL API's database URI. + file: ../../../artifacts/secrets/postgraphile-connection.secret + postgraphile-jwt-secret: + # The GraphQL API's JWT secret. + file: ../../../artifacts/secrets/postgraphile-jwt-secret.secret + postgraphile-owner-connection: + # The GraphQL API's database owner URI. + file: ../../../artifacts/secrets/postgraphile-owner-connection.secret +services: + postgraphile: + # You can access the GraphQL API for the PostgreSQL database at [postgraphile.app.localhost](https://postgraphile.app.localhost/). + deploy: + labels: + - dargstack.development.build=../../../../postgraphile + - dargstack.profiles=default + - traefik.enable=true + - traefik.http.middlewares.postgraphile-auth.forwardauth.address=http://vibetype:3000/api/internal/service/postgraphile/authentication + - traefik.http.middlewares.postgraphile-auth.forwardauth.forwardBody=true + - traefik.http.middlewares.postgraphile-auth.forwardauth.preserveRequestMethod=true + - traefik.http.middlewares.postgraphile-cors.headers.accessControlAllowCredentials=true + - traefik.http.middlewares.postgraphile-cors.headers.accessControlAllowHeaders=authorization + - traefik.http.middlewares.postgraphile-cors.headers.accessControlAllowOriginList=https://${STACK_DOMAIN},https://localhost:3000,https://app.localhost:3000 + - traefik.http.routers.postgraphile.entryPoints=web + - traefik.http.routers.postgraphile.middlewares=redirectscheme # dargstack:dev-only + - traefik.http.routers.postgraphile.rule=Host(`postgraphile.${STACK_DOMAIN}`) + - traefik.http.routers.postgraphile-secure.entryPoints=web-secure + - traefik.http.routers.postgraphile-secure.middlewares=postgraphile-auth,postgraphile-cors + - traefik.http.routers.postgraphile-secure.rule=Host(`postgraphile.${STACK_DOMAIN}`) && Path(`/graphql`) + - traefik.http.routers.postgraphile-secure.tls.options=mintls13@file # dargstack:dev-only + - traefik.http.routers.postgraphile-secure-graphiql.entryPoints=web-secure + - traefik.http.routers.postgraphile-secure-graphiql.rule=Host(`postgraphile.${STACK_DOMAIN}`) + - traefik.http.routers.postgraphile-secure-graphiql.tls.options=mintls13@file # dargstack:dev-only + - traefik.http.services.postgraphile.loadbalancer.server.port=5678 + # # Use the DEBUG environment variable for extended debugging. + # environment: + # DEBUG: graphile-build:warn,graphile-build-pg:sql + image: vibetype/postgraphile:development + secrets: + - source: postgraphile-connection + target: /run/environment-variables/POSTGRAPHILE_CONNECTION + - source: postgraphile-jwt-secret + target: /run/environment-variables/POSTGRAPHILE_JWT_SECRET_KEY + - source: postgraphile-owner-connection + target: /run/environment-variables/POSTGRAPHILE_OWNER_CONNECTION + volumes: + - ../../../../postgraphile/:/srv/app/ # dargstack:dev-only + - ./configurations/jwtRS256.key.pub:/run/environment-variables/POSTGRAPHILE_JWT_PUBLIC_KEY:ro + - pnpm-data:/srv/.pnpm-store/ # dargstack:dev-only + - postgraphile-data:/srv/app/node_modules # dargstack:dev-only +volumes: + postgraphile-data: + # The GraphQL API's data. + {} +x-dargstack: + secrets: + postgraphile-connection: + type: template + template: postgres://{{secret:postgres-role-service-postgraphile-username}}:{{secret:postgres-role-service-postgraphile-password}}@postgres:5432/{{secret:postgres-db}} + postgraphile-jwt-secret: + type: private_key + postgraphile-owner-connection: + type: template + template: postgres://{{secret:postgres-user}}:{{secret:postgres-password}}@postgres:5432/{{secret:postgres-db}} diff --git a/src/development/configurations/postgraphile/jwtRS256.key.pub b/src/development/postgraphile/configurations/jwtRS256.key.pub similarity index 100% rename from src/development/configurations/postgraphile/jwtRS256.key.pub rename to src/development/postgraphile/configurations/jwtRS256.key.pub diff --git a/src/development/secrets/postgraphile/connection.secret.template b/src/development/postgraphile/secrets/connection.secret.template similarity index 100% rename from src/development/secrets/postgraphile/connection.secret.template rename to src/development/postgraphile/secrets/connection.secret.template diff --git a/src/development/secrets/postgraphile/jwt-secret.secret.template b/src/development/postgraphile/secrets/jwt-secret.secret.template similarity index 100% rename from src/development/secrets/postgraphile/jwt-secret.secret.template rename to src/development/postgraphile/secrets/jwt-secret.secret.template diff --git a/src/development/secrets/postgraphile/owner-connection.secret.template b/src/development/postgraphile/secrets/owner-connection.secret.template similarity index 100% rename from src/development/secrets/postgraphile/owner-connection.secret.template rename to src/development/postgraphile/secrets/owner-connection.secret.template diff --git a/src/development/postgres/compose.yaml b/src/development/postgres/compose.yaml new file mode 100644 index 00000000..19af7499 --- /dev/null +++ b/src/development/postgres/compose.yaml @@ -0,0 +1,92 @@ +secrets: + postgres-db: + # The database's name. + file: ../../../artifacts/secrets/postgres-db.secret + postgres-password: + # The database's password. + file: ../../../artifacts/secrets/postgres-password.secret + postgres-role-service-grafana-password: + # The password of the observation dashboard's database role. + file: ../../../artifacts/secrets/postgres-role-service-grafana-password.secret + postgres-role-service-grafana-username: + # The username of the observation dashboard's database role. + file: ../../../artifacts/secrets/postgres-role-service-grafana-username.secret + postgres-role-service-postgraphile-password: + # The password of the GraphQL API database wrapper's database role. + file: ../../../artifacts/secrets/postgres-role-service-postgraphile-password.secret + postgres-role-service-postgraphile-username: + # The username of the GraphQL API database wrapper's database role. + file: ../../../artifacts/secrets/postgres-role-service-postgraphile-username.secret + postgres-role-service-vibetype-password: + # The `tusd` database role's password. + file: ../../../artifacts/secrets/postgres-role-service-vibetype-password.secret + postgres-role-service-vibetype-username: + # The `tusd` database role's password. + file: ../../../artifacts/secrets/postgres-role-service-vibetype-username.secret + postgres-role-service-zammad-password: + # The password of the customer service database role. + file: ../../../artifacts/secrets/postgres-role-service-zammad-password.secret + postgres-role-service-zammad-username: + # The username of the customer service database role. + file: ../../../artifacts/secrets/postgres-role-service-zammad-username.secret + postgres-user: + # The database's default user. + file: ../../../artifacts/secrets/postgres-user.secret +services: + postgres: + # You can access the database via `adminer`. + command: -c vibetype.jwt_expiry_duration='1 month' -c wal_level=logical + deploy: + labels: + - dargstack.profiles=default + environment: + POSTGRES_DB_FILE: /run/secrets/postgres-db + POSTGRES_PASSWORD_FILE: /run/secrets/postgres-password + POSTGRES_USER_FILE: /run/secrets/postgres-user + image: postgis/postgis:18-3.6-alpine + ports: # dargstack:dev-only + - 5432:5432 # dargstack:dev-only + secrets: + - postgres-db + - postgres-password + - postgres-user + # sysctls: + # # Prevent Docker Swarm from killing connections (https://github.com/moby/moby/issues/31208) + # - net.ipv4.tcp_keepalive_time=600 + # - net.ipv4.tcp_keepalive_intvl=30 + # - net.ipv4.tcp_keepalive_probes=10 + volumes: + - postgres-data:/var/lib/postgresql/ +volumes: + postgres-data: + # The database's data. + {} +x-dargstack: + secrets: + postgres-db: + type: word + postgres-password: + special_characters: false + type: random_string + postgres-role-service-grafana-password: + special_characters: false + type: random_string + postgres-role-service-grafana-username: + type: word + postgres-role-service-postgraphile-password: + special_characters: false + type: random_string + postgres-role-service-postgraphile-username: + type: word + postgres-role-service-vibetype-password: + special_characters: false + type: random_string + postgres-role-service-vibetype-username: + type: word + postgres-role-service-zammad-password: + special_characters: false + type: random_string + postgres-role-service-zammad-username: + type: word + postgres-user: + type: word diff --git a/src/development/secrets/postgres/db.secret b/src/development/postgres/secrets/db.secret.old similarity index 100% rename from src/development/secrets/postgres/db.secret rename to src/development/postgres/secrets/db.secret.old diff --git a/src/development/secrets/elasticsearch/keystore_password.secret.template b/src/development/postgres/secrets/db.secret.template.old similarity index 100% rename from src/development/secrets/elasticsearch/keystore_password.secret.template rename to src/development/postgres/secrets/db.secret.template.old diff --git a/src/development/secrets/elasticsearch/password.secret.template b/src/development/postgres/secrets/password.secret.template similarity index 100% rename from src/development/secrets/elasticsearch/password.secret.template rename to src/development/postgres/secrets/password.secret.template diff --git a/src/development/secrets/postgres/role_service_grafana_password.secret.template b/src/development/postgres/secrets/role_service_grafana_password.secret.template similarity index 100% rename from src/development/secrets/postgres/role_service_grafana_password.secret.template rename to src/development/postgres/secrets/role_service_grafana_password.secret.template diff --git a/src/development/secrets/postgres/role_service_grafana_username.secret.template b/src/development/postgres/secrets/role_service_grafana_username.secret.template similarity index 100% rename from src/development/secrets/postgres/role_service_grafana_username.secret.template rename to src/development/postgres/secrets/role_service_grafana_username.secret.template diff --git a/src/development/secrets/postgres/role_service_postgraphile_password.secret.template b/src/development/postgres/secrets/role_service_postgraphile_password.secret.template similarity index 100% rename from src/development/secrets/postgres/role_service_postgraphile_password.secret.template rename to src/development/postgres/secrets/role_service_postgraphile_password.secret.template diff --git a/src/development/secrets/postgres/role_service_postgraphile_username.secret.template b/src/development/postgres/secrets/role_service_postgraphile_username.secret.template similarity index 100% rename from src/development/secrets/postgres/role_service_postgraphile_username.secret.template rename to src/development/postgres/secrets/role_service_postgraphile_username.secret.template diff --git a/src/development/secrets/postgres/role_service_vibetype_password.secret.template b/src/development/postgres/secrets/role_service_vibetype_password.secret.template similarity index 100% rename from src/development/secrets/postgres/role_service_vibetype_password.secret.template rename to src/development/postgres/secrets/role_service_vibetype_password.secret.template diff --git a/src/development/secrets/postgres/role_service_vibetype_username.secret.template b/src/development/postgres/secrets/role_service_vibetype_username.secret.template similarity index 100% rename from src/development/secrets/postgres/role_service_vibetype_username.secret.template rename to src/development/postgres/secrets/role_service_vibetype_username.secret.template diff --git a/src/development/secrets/postgres/role_service_zammad_password.secret.template b/src/development/postgres/secrets/role_service_zammad_password.secret.template similarity index 100% rename from src/development/secrets/postgres/role_service_zammad_password.secret.template rename to src/development/postgres/secrets/role_service_zammad_password.secret.template diff --git a/src/development/secrets/postgres/role_service_zammad_username.secret.template b/src/development/postgres/secrets/role_service_zammad_username.secret.template similarity index 100% rename from src/development/secrets/postgres/role_service_zammad_username.secret.template rename to src/development/postgres/secrets/role_service_zammad_username.secret.template diff --git a/src/development/secrets/postgres/user.secret.template b/src/development/postgres/secrets/user.secret.template similarity index 100% rename from src/development/secrets/postgres/user.secret.template rename to src/development/postgres/secrets/user.secret.template diff --git a/src/development/prometheus/compose.yaml b/src/development/prometheus/compose.yaml new file mode 100644 index 00000000..4c393d3c --- /dev/null +++ b/src/development/prometheus/compose.yaml @@ -0,0 +1,22 @@ +services: + prometheus: + # You can access the metrics monitoring at [prometheus.app.localhost](https://prometheus.app.localhost/). + deploy: + labels: + - dargstack.profiles=analytics + - traefik.enable=true + - traefik.http.routers.prometheus.entryPoints=web + - traefik.http.routers.prometheus.middlewares=redirectscheme # dargstack:dev-only + - traefik.http.routers.prometheus.rule=Host(`prometheus.${STACK_DOMAIN}`) + - traefik.http.routers.prometheus-secure.entryPoints=web-secure + - traefik.http.routers.prometheus-secure.rule=Host(`prometheus.${STACK_DOMAIN}`) + - traefik.http.routers.prometheus-secure.tls.options=mintls13@file # dargstack:dev-only + - traefik.http.services.prometheus.loadbalancer.server.port=9090 + image: prom/prometheus:v3.10.0 + volumes: + - ./configurations/prometheus.yaml:/etc/prometheus/prometheus.yml:ro + - prometheus-data:/prometheus +volumes: + prometheus-data: + # The metrics monitoring's data. + {} diff --git a/src/production/configurations/prometheus/prometheus.yaml b/src/development/prometheus/configurations/prometheus.yaml similarity index 97% rename from src/production/configurations/prometheus/prometheus.yaml rename to src/development/prometheus/configurations/prometheus.yaml index 372a7580..0f7725eb 100644 --- a/src/production/configurations/prometheus/prometheus.yaml +++ b/src/development/prometheus/configurations/prometheus.yaml @@ -32,4 +32,4 @@ scrape_configs: static_configs: - targets: - redpanda:9644 - metrics_path: /public_metrics \ No newline at end of file + metrics_path: /public_metrics diff --git a/src/development/reccoom/compose.yaml b/src/development/reccoom/compose.yaml new file mode 100644 index 00000000..97a254e5 --- /dev/null +++ b/src/development/reccoom/compose.yaml @@ -0,0 +1,64 @@ +secrets: + reccoom-ingest-api-key: + # The AI provider's API key for the recommendation engine. + file: ../../../artifacts/secrets/reccoom-ingest-api-key.secret + reccoom-openai-api-key: + # The AI provider's API key for the recommendation engine. + file: ../../../artifacts/secrets/reccoom-openai-api-key.secret +services: + reccoom: + # You cannot access the recommendation service directly. + deploy: + labels: + - dargstack.development.build=../../../../reccoom + - dargstack.profiles=recommendation + - traefik.enable=true + - traefik.http.routers.reccoom.entryPoints=web + - traefik.http.routers.reccoom.middlewares=redirectscheme # dargstack:dev-only + - traefik.http.routers.reccoom.rule=Host(`reccoom.${STACK_DOMAIN}`) + - traefik.http.routers.reccoom-secure.entryPoints=web-secure + - traefik.http.routers.reccoom-secure.rule=Host(`reccoom.${STACK_DOMAIN}`) + - traefik.http.routers.reccoom-secure.tls.options=mintls13@file # dargstack:dev-only + - traefik.http.services.reccoom.loadbalancer.server.port=5245 + environment: + POSTGRES_HOST: postgres + RECCOOM_POSTGRES_HOST: reccoom_postgres + image: vibetype/reccoom:development + secrets: + - postgres-db + - postgres-password + - postgres-user + - source: reccoom-ingest-api-key + target: /run/environment-variables/INGEST_API_KEY + - reccoom-openai-api-key + volumes: + - ../../../../reccoom/:/srv/app/ # dargstack:dev-only + - ../postgraphile/configurations/jwtRS256.key.pub:/run/configurations/jwtRS256.key.pub:ro + reccoom_postgres: + # You can access reccoom's database via `adminer`. + deploy: + labels: + - dargstack.profiles=recommendation + environment: + POSTGRES_DB_FILE: /run/secrets/postgres-db + POSTGRES_PASSWORD_FILE: /run/secrets/postgres-password + POSTGRES_USER_FILE: /run/secrets/postgres-user + image: pgvector/pgvector:0.8.2-pg18 + ports: # dargstack:dev-only + - 5433:5432 # dargstack:dev-only + secrets: + - postgres-db + - postgres-password + - postgres-user + volumes: + - reccoom-postgres-data:/var/lib/postgresql/ +volumes: + reccoom-postgres-data: + # The recommendation database's data. + {} +x-dargstack: + secrets: + reccoom-ingest-api-key: + type: third_party + reccoom-openai-api-key: + type: third_party diff --git a/src/development/secrets/reccoom/ingest-api-key.secret.template b/src/development/reccoom/secrets/ingest-api-key.secret.template similarity index 100% rename from src/development/secrets/reccoom/ingest-api-key.secret.template rename to src/development/reccoom/secrets/ingest-api-key.secret.template diff --git a/src/development/secrets/reccoom/openai-api-key.secret.template b/src/development/reccoom/secrets/openai-api-key.secret.template similarity index 100% rename from src/development/secrets/reccoom/openai-api-key.secret.template rename to src/development/reccoom/secrets/openai-api-key.secret.template diff --git a/src/development/redis/compose.yaml b/src/development/redis/compose.yaml new file mode 100644 index 00000000..4fe89a5b --- /dev/null +++ b/src/development/redis/compose.yaml @@ -0,0 +1,13 @@ +services: + redis: + # You cannot access the caching system via a web interface. + deploy: + labels: + - dargstack.profiles=zammad + image: redis:8.6.1-alpine + volumes: + - redis-data:/data +volumes: + redis-data: + # The caching system's data. + {} diff --git a/src/development/redpanda/compose.yaml b/src/development/redpanda/compose.yaml new file mode 100644 index 00000000..a92a858b --- /dev/null +++ b/src/development/redpanda/compose.yaml @@ -0,0 +1,45 @@ +services: + redpanda: + # You can access the event streaming platform's ui as described under `redpanda-console`. + command: + - redpanda start + - --mode dev-container # dargstack:dev-only + - --kafka-addr internal://0.0.0.0:9092,external://0.0.0.0:19092 + - --advertise-kafka-addr internal://redpanda:9092,external://localhost:19092 + - --pandaproxy-addr internal://0.0.0.0:8082,external://0.0.0.0:18082 + - --advertise-pandaproxy-addr internal://redpanda:8082,external://localhost:18082 + - --schema-registry-addr internal://0.0.0.0:8081,external://0.0.0.0:18081 + deploy: + labels: + - dargstack.profiles=event-streaming + # healthcheck: + # test: ["CMD-SHELL", "output=$(rpk cluster health --json); echo \"$output\" | grep -q '\"healthy\":true' || { echo \"$output\"; exit 1; }"] + # interval: 30s + # timeout: 10s + # retries: 3 + # start_period: 10s + image: redpandadata/redpanda:v25.3.10 + volumes: + - redpanda-data:/var/lib/redpanda/data + redpanda-console: + # You can access the event streaming platform's ui at [redpanda.app.localhost](https://redpanda.app.localhost/). + deploy: + labels: + - dargstack.profiles=event-streaming + - traefik.enable=true + - traefik.http.routers.redpanda.entryPoints=web + - traefik.http.routers.redpanda.middlewares=redirectscheme # dargstack:dev-only + - traefik.http.routers.redpanda.rule=Host(`redpanda.${STACK_DOMAIN}`) + - traefik.http.routers.redpanda-secure.entryPoints=web-secure + - traefik.http.routers.redpanda-secure.rule=Host(`redpanda.${STACK_DOMAIN}`) + - traefik.http.routers.redpanda-secure.tls.options=mintls13@file # dargstack:dev-only + - traefik.http.services.redpanda.loadbalancer.server.port=8080 + environment: + CONFIG_FILEPATH: /srv/app/redpanda-config.yaml + image: redpandadata/console:v3.5.3 + volumes: + - ./configurations/config.yaml:/srv/app/redpanda-config.yaml:ro +volumes: + redpanda-data: + # The message queue's data. + {} diff --git a/src/production/configurations/redpanda/config.yaml b/src/development/redpanda/configurations/config.yaml similarity index 58% rename from src/production/configurations/redpanda/config.yaml rename to src/development/redpanda/configurations/config.yaml index 26876a8a..93bf566c 100644 --- a/src/production/configurations/redpanda/config.yaml +++ b/src/development/redpanda/configurations/config.yaml @@ -1,12 +1,12 @@ kafka: brokers: - - redpanda:9092 + - redpanda:9092 redpanda: adminApi: enabled: true urls: - - http://redpanda:9644 + - http://redpanda:9644 schemaRegistry: enabled: true urls: - - http://redpanda:8081 + - http://redpanda:8081 diff --git a/src/development/secrets/elasticsearch/keystore_password.secret b/src/development/secrets/elasticsearch/keystore_password.secret deleted file mode 100644 index f3f85cae..00000000 --- a/src/development/secrets/elasticsearch/keystore_password.secret +++ /dev/null @@ -1 +0,0 @@ -elastic \ No newline at end of file diff --git a/src/development/secrets/elasticsearch/password.secret b/src/development/secrets/elasticsearch/password.secret deleted file mode 100644 index f3f85cae..00000000 --- a/src/development/secrets/elasticsearch/password.secret +++ /dev/null @@ -1 +0,0 @@ -elastic \ No newline at end of file diff --git a/src/development/secrets/grafana/admin_email.secret b/src/development/secrets/grafana/admin_email.secret deleted file mode 100644 index 06474a56..00000000 --- a/src/development/secrets/grafana/admin_email.secret +++ /dev/null @@ -1 +0,0 @@ -admin@localhost \ No newline at end of file diff --git a/src/development/secrets/grafana/admin_email.secret.template b/src/development/secrets/grafana/admin_email.secret.template deleted file mode 100644 index a6bb01c1..00000000 --- a/src/development/secrets/grafana/admin_email.secret.template +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/development/secrets/grafana/admin_password.secret b/src/development/secrets/grafana/admin_password.secret deleted file mode 100644 index 6da70038..00000000 --- a/src/development/secrets/grafana/admin_password.secret +++ /dev/null @@ -1 +0,0 @@ -grafana \ No newline at end of file diff --git a/src/development/secrets/grafana/admin_password.secret.template b/src/development/secrets/grafana/admin_password.secret.template deleted file mode 100644 index a6bb01c1..00000000 --- a/src/development/secrets/grafana/admin_password.secret.template +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/development/secrets/grafana/admin_user.secret b/src/development/secrets/grafana/admin_user.secret deleted file mode 100644 index 6da70038..00000000 --- a/src/development/secrets/grafana/admin_user.secret +++ /dev/null @@ -1 +0,0 @@ -grafana \ No newline at end of file diff --git a/src/development/secrets/grafana/admin_user.secret.template b/src/development/secrets/grafana/admin_user.secret.template deleted file mode 100644 index a6bb01c1..00000000 --- a/src/development/secrets/grafana/admin_user.secret.template +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/development/secrets/grafana/discord_webhook.secret b/src/development/secrets/grafana/discord_webhook.secret deleted file mode 100644 index 6075c4fb..00000000 --- a/src/development/secrets/grafana/discord_webhook.secret +++ /dev/null @@ -1 +0,0 @@ -UNSET THIRD PARTY SECRET \ No newline at end of file diff --git a/src/development/secrets/grafana/discord_webhook.secret.template b/src/development/secrets/grafana/discord_webhook.secret.template deleted file mode 100644 index 3ad15b2a..00000000 --- a/src/development/secrets/grafana/discord_webhook.secret.template +++ /dev/null @@ -1 +0,0 @@ -https://discord.com/api/webhooks// \ No newline at end of file diff --git a/src/development/secrets/jobber/aliases.secret b/src/development/secrets/jobber/aliases.secret deleted file mode 100644 index 20df8a23..00000000 --- a/src/development/secrets/jobber/aliases.secret +++ /dev/null @@ -1 +0,0 @@ -default: mail@localhost diff --git a/src/development/secrets/jobber/aws-bucket.secret b/src/development/secrets/jobber/aws-bucket.secret deleted file mode 100644 index dc9cb35b..00000000 --- a/src/development/secrets/jobber/aws-bucket.secret +++ /dev/null @@ -1 +0,0 @@ -vibetype-backup \ No newline at end of file diff --git a/src/development/secrets/jobber/aws-configuration.secret b/src/development/secrets/jobber/aws-configuration.secret deleted file mode 100644 index 20ea0b02..00000000 --- a/src/development/secrets/jobber/aws-configuration.secret +++ /dev/null @@ -1,16 +0,0 @@ -[default] -region = auto - -s3 = - endpoint_url = http://minio:9000 - signature_version = s3v4 - max_concurrent_requests = 100 - max_queue_size = 1000 - multipart_threshold = 50MB - # Edit the multipart_chunksize value according to the file sizes that you want to upload. The present configuration allows to upload files up to 10 GB (100 requests * 10MB). For example setting it to 5GB allows you to upload files up to 5TB. - multipart_chunksize = 10MB -s3api = - endpoint_url = http://minio:9000 - -[plugins] -endpoint = awscli_plugin_endpoint \ No newline at end of file diff --git a/src/development/secrets/jobber/aws-credentials.secret b/src/development/secrets/jobber/aws-credentials.secret deleted file mode 100644 index a28cae87..00000000 --- a/src/development/secrets/jobber/aws-credentials.secret +++ /dev/null @@ -1,3 +0,0 @@ -[default] -aws_access_key_id = s3user -aws_secret_access_key = s3password diff --git a/src/development/secrets/jobber/msmtprc.secret b/src/development/secrets/jobber/msmtprc.secret deleted file mode 100644 index 84ceec08..00000000 --- a/src/development/secrets/jobber/msmtprc.secret +++ /dev/null @@ -1,17 +0,0 @@ -# Set default values for all following accounts. -defaults -auth off -tls off -tls_trust_file /etc/ssl/certs/ca-certificates.crt -syslog on - -# localhost -account localhost -host localhost -port 25 -from mail@localhost -user mail@localhost - -# Set a default account -account default : localhost -aliases /etc/aliases diff --git a/src/development/secrets/portainer/admin-password.secret b/src/development/secrets/portainer/admin-password.secret deleted file mode 100644 index 45aee45f..00000000 --- a/src/development/secrets/portainer/admin-password.secret +++ /dev/null @@ -1 +0,0 @@ -123456123456 \ No newline at end of file diff --git a/src/development/secrets/postgraphile/connection.secret b/src/development/secrets/postgraphile/connection.secret deleted file mode 100644 index f94cfa39..00000000 --- a/src/development/secrets/postgraphile/connection.secret +++ /dev/null @@ -1 +0,0 @@ -postgresql://postgraphile:postgraphile@postgres/vibetype \ No newline at end of file diff --git a/src/development/secrets/postgraphile/jwt-secret.secret b/src/development/secrets/postgraphile/jwt-secret.secret deleted file mode 100644 index 8b5b34e0..00000000 --- a/src/development/secrets/postgraphile/jwt-secret.secret +++ /dev/null @@ -1,51 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIJKQIBAAKCAgEAtBuHX2uH5GviLbocSUBKaRE4iKEjjEoB1eh7VQdBoKi1Wd+D -NUilVyCtq0ootPSDR/8yOTa8W396Wu1xm07+xDAyFzsilIppu8DNcJo28Gb3PZCm -4nXmITPkknVSKf80hosgauoe7itqDxgMASYTU8CgBH8zXPaowhqzjz0M/T9RqD1m -RzMn3NEprDnaVAsh11r3DSandHjsnlgKCf1dlh4ixCZ6zUhtb0sT6GxuJaGjNVev -LbPLuugMTu3d484FwbND+AmpAjIgdnX5lJQneT7HxgnaiwLDazSwLM0jmiyEvnrm -SPJZ2sgp87XS0VTVwMYk3M3RCy/3RiamJG5v7qZuVr4L87cXWvLHCwV5dGaPu0Dc -3/75lcKcWy+BtBQUI+n+om1EitLtUo+lxE9aSyG6bhYQNu+XMRwY768TrzrvBwYt -5JxoO9y3ybIFzoi/mufkp2NY7XB7CHfMcrn3XzCBbXJwt0Zlu2K1R8FPVN0Slsjt -OVQun1al9cjC808hihjpiiGpKURoaFsxkh4B8n2Qli/fl5BQVAPClmFbsvToSzy+ -ENEDpXc53eve5Dhzx5SB/qe0DwlljDdc2W8nhozYHaOtnLnhG/TU9mmOliw5jmsH -b5m1OMdBXMEhrGv4hkHJNg9+hCSJDzvbFRkNY95lZj/fbtFrSHR5WwdsgI8CAwEA -AQKCAgEAjxyMvbJpAYUD7MfEcCQovEHVxSMdZvzrZnhbf53LdQh5SZeD35QA5TFv -Lfs4S0k7A7twweuPUbkClTu1GO51G5kcRD9V4+fzyh+SXpX7b5yxenb1VF7QZLOi -PQoCJqLFrt7f/HRZ7XALz0CRUVxa4SLfQ5N7UbQhNlMXOIsPRi/JB8D6AztPwnNl -BJfXtw49bqy2P/nl93OauNtF5tgvQ/hgMbJNw854PoXOpNF72GUOlXU+GjeSe8qk -9RanSLtM8bQrHu02ISuJhfeKQJhUoU/UV7U+tVSVyRrNnlvGnVwggmaPk4kXAvQn -+aIRiQo66vnHErhsEdKkTlapj6s9PnMmtwNJcv/Bp8/621Pr3mqG4WtZrYxMYFzN -5tXwjkQQRpLRyi0pwu6IHj9w+y83oJKi6HTo//tJbKEzqx1jjhl4FiNwKMDfxlpp -eN52c723DELgc9AhRCXP50z2OnjByeI296bj+Vyv0noDDSLK5pq4Hm9Ck62NCfsV -YqCmvVu5JwFP+MYUECNRH6d98wsWhgKvAJe37JH9BEjxvW3oLB4XofSqGrFePNEM -jRdnLdJxFC0AfWVMu4JW1MvcZct7nkFd91YGKzZRlasbnRVQ4qHTYhojwiM2LF8E -aLxKOKegxfRFBkfHSzxzXAA2o4r2pJo2WZI+lBuBd6TmTX21ZLkCggEBAOiIkB9k -oOOe0UyVDkEJTk62y5LdrEG3KpEjaW12qFP1IGgqP5gDqhDQQ4WB4Pqzl1uoqy2L -WafpfEH2lBTeYMV4Wg5WkgZIrCRthhdwoDqluUttN612VuT4QlLvnB37zdDzkzfL -asnCKmXfaOSU/qvHcUvS6SgnwKVWBqFSB2VWBgLGVH2Ty/Yc9TpMraSZA2ATnieR -7aZy1zegwp7n3sO3mmY0w7A+7YoUms1+Ibe5aNmyw/ThDJBkx+UG0nv9qpoA4yNH -+S355EJyYdUNoh0d8D3COk72YjcODmiB+6W0qoPQ3SeQ2X/6+xvFNkx2/34+nhcy -tNNqBkeKe2IpkzUCggEBAMZIjpAPiT/7rb0/ea8DZAmdOhjER5NOic3gz6RN7oqj -MQ2ktzxfGJez+wnjaqv1xF+qwZi69JwflK3FWIZR3G1wlO5pKMkef5l1N/VLvW2k -opfx+82sVXi/Cx7w8o6IAS60ZjyxTWhnYQ695QIKP79+poWJ3zi9sBpsj7hHbPco -tu4kJKVpXOVcmMluSqrn+3kT7Xlpqy6qnFBggRHLJD9okM3TLU3znHRUFhViova3 -kyD65qViITUCIMDmigfCbFYLVGEdNyMDBH0OGSUaSwY0d/KS+43JxLeh84ylHPYZ -tfPiQxCxn2VyD2h4XkNIdgoY7f/NbkzjkLEdSdc0GTMCggEBAJzgdQsY4opt/RpD -fUhXNONZ42GD99Cl+CvOzjOxV8K8n05nIlw2LKgHOWZ6xwOb4cNOuZ2SY7wqg1Al -QKYLmRHgLjF6Ki3fHXO+CDcMHq0yXR4L4wI90kXLT0OQr6xy0tnjWjDMJZFUUzJD -VQrRkjbl6QOUmQQkPY3Nyc9P/flZ3dhFYX8PFQ1HYBIi5Qskx+grlAlyI/ilhZjb -9jEqkVlNJvdJJbRj3/HGEOIN9EV06s3kEtvEcKuBsnJK9fn8mvonGxYUWoGwE1TY -wjPwbKxkJE4mGRxokL4/12yeNN4IUvl3EZy91l7HPl3v4MAZkCjlqdZQuTngT7g4 -LyF8lvkCggEAQJIUSvmkOn/dPknTeJjkFPVsm/AfVus2mSLiu6DdU6x9JvJC8ZgO -TCjCUaALduBcCMN0tCX9znHCWyxu/Z7e54zIEzOPop8Z8oFnravyjigVAuI8m+fJ -Fb8xAex5MM09hVYeDRm4GY3A36obT6TCybuWwtn5JWMwXAqKavpnk71ghQCkJnG/ -XLngz4fpLOrKy80fgnBU3KeWq94hagf7T+LfdQeWM1Jn2sIfRuuOIkX51b2fKrBg -HAELZYYt4QUBfqvF2LJI6E/tQEQ9EAYV9HlVrlsLLEtOknZc96o1WjdZN4ixSlht -jf2s4tp/5+1K81LW/nyJtOROlD7zcu92XQKCAQAUgxlfDbjBz64DrpyJDhHQq89X -WH0+zXhwuWiQwzlbSQUJnKnVwPwcnKD/zxK601fWT26C01l3senX49zy/KZI1BtD -mco+Mr+wKGNPcOoVhhzYTDk6R+jfsyel0uXcky6LPncCLgsq7UpVylONaDO5m+fL -2wUg67tJu13zHMSWml5+o51jY/Qn/UjsSyEj7gQHq4xM2ottb6fh3CgmMvJKjrAP -juM36ePNpeQMBHf9Djt7a/tuN0OZdGo4sjBSJ9fEAoMGtxZ1nQyu06ncBQMtlqeD -+pzL73569phIJDX7E11wczzx/QObJ4dMznCgqEfpzlSNOhPl+bqyzAdVXO4V ------END RSA PRIVATE KEY----- diff --git a/src/development/secrets/postgraphile/owner-connection.secret b/src/development/secrets/postgraphile/owner-connection.secret deleted file mode 100644 index 093bbed2..00000000 --- a/src/development/secrets/postgraphile/owner-connection.secret +++ /dev/null @@ -1 +0,0 @@ -postgresql://postgres:postgres@postgres/vibetype \ No newline at end of file diff --git a/src/development/secrets/postgres/db.secret.template b/src/development/secrets/postgres/db.secret.template deleted file mode 100644 index a6bb01c1..00000000 --- a/src/development/secrets/postgres/db.secret.template +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/development/secrets/postgres/password.secret b/src/development/secrets/postgres/password.secret deleted file mode 100644 index f1349944..00000000 --- a/src/development/secrets/postgres/password.secret +++ /dev/null @@ -1 +0,0 @@ -postgres diff --git a/src/development/secrets/postgres/password.secret.template b/src/development/secrets/postgres/password.secret.template deleted file mode 100644 index a6bb01c1..00000000 --- a/src/development/secrets/postgres/password.secret.template +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/development/secrets/postgres/role_service_grafana_password.secret b/src/development/secrets/postgres/role_service_grafana_password.secret deleted file mode 100644 index 6da70038..00000000 --- a/src/development/secrets/postgres/role_service_grafana_password.secret +++ /dev/null @@ -1 +0,0 @@ -grafana \ No newline at end of file diff --git a/src/development/secrets/postgres/role_service_grafana_username.secret b/src/development/secrets/postgres/role_service_grafana_username.secret deleted file mode 100644 index 6da70038..00000000 --- a/src/development/secrets/postgres/role_service_grafana_username.secret +++ /dev/null @@ -1 +0,0 @@ -grafana \ No newline at end of file diff --git a/src/development/secrets/postgres/role_service_postgraphile_password.secret b/src/development/secrets/postgres/role_service_postgraphile_password.secret deleted file mode 100644 index a4da12ec..00000000 --- a/src/development/secrets/postgres/role_service_postgraphile_password.secret +++ /dev/null @@ -1 +0,0 @@ -postgraphile \ No newline at end of file diff --git a/src/development/secrets/postgres/role_service_postgraphile_username.secret b/src/development/secrets/postgres/role_service_postgraphile_username.secret deleted file mode 100644 index a4da12ec..00000000 --- a/src/development/secrets/postgres/role_service_postgraphile_username.secret +++ /dev/null @@ -1 +0,0 @@ -postgraphile \ No newline at end of file diff --git a/src/development/secrets/postgres/role_service_vibetype_password.secret b/src/development/secrets/postgres/role_service_vibetype_password.secret deleted file mode 100644 index 5e84b8c8..00000000 --- a/src/development/secrets/postgres/role_service_vibetype_password.secret +++ /dev/null @@ -1 +0,0 @@ -tusd \ No newline at end of file diff --git a/src/development/secrets/postgres/role_service_vibetype_username.secret b/src/development/secrets/postgres/role_service_vibetype_username.secret deleted file mode 100644 index 9294c3d9..00000000 --- a/src/development/secrets/postgres/role_service_vibetype_username.secret +++ /dev/null @@ -1 +0,0 @@ -vibetype \ No newline at end of file diff --git a/src/development/secrets/postgres/role_service_zammad_password.secret b/src/development/secrets/postgres/role_service_zammad_password.secret deleted file mode 100644 index 70699eae..00000000 --- a/src/development/secrets/postgres/role_service_zammad_password.secret +++ /dev/null @@ -1 +0,0 @@ -zammad \ No newline at end of file diff --git a/src/development/secrets/postgres/role_service_zammad_username.secret b/src/development/secrets/postgres/role_service_zammad_username.secret deleted file mode 100644 index 70699eae..00000000 --- a/src/development/secrets/postgres/role_service_zammad_username.secret +++ /dev/null @@ -1 +0,0 @@ -zammad \ No newline at end of file diff --git a/src/development/secrets/postgres/user.secret b/src/development/secrets/postgres/user.secret deleted file mode 100644 index f1349944..00000000 --- a/src/development/secrets/postgres/user.secret +++ /dev/null @@ -1 +0,0 @@ -postgres diff --git a/src/development/secrets/reccoom/ingest-api-key.secret b/src/development/secrets/reccoom/ingest-api-key.secret deleted file mode 100644 index 6075c4fb..00000000 --- a/src/development/secrets/reccoom/ingest-api-key.secret +++ /dev/null @@ -1 +0,0 @@ -UNSET THIRD PARTY SECRET \ No newline at end of file diff --git a/src/development/secrets/reccoom/openai-api-key.secret b/src/development/secrets/reccoom/openai-api-key.secret deleted file mode 100644 index 6075c4fb..00000000 --- a/src/development/secrets/reccoom/openai-api-key.secret +++ /dev/null @@ -1 +0,0 @@ -UNSET THIRD PARTY SECRET \ No newline at end of file diff --git a/src/development/secrets/sqitch/target.secret b/src/development/secrets/sqitch/target.secret deleted file mode 100644 index 12789f3c..00000000 --- a/src/development/secrets/sqitch/target.secret +++ /dev/null @@ -1 +0,0 @@ -db:pg://postgres:postgres@postgres/vibetype \ No newline at end of file diff --git a/src/development/secrets/tusd/aws.secret b/src/development/secrets/tusd/aws.secret deleted file mode 100644 index eed88684..00000000 --- a/src/development/secrets/tusd/aws.secret +++ /dev/null @@ -1,3 +0,0 @@ -[default] -aws_access_key_id = s3user -aws_secret_access_key = s3password \ No newline at end of file diff --git a/src/development/secrets/vibetype/api-notification.secret b/src/development/secrets/vibetype/api-notification.secret deleted file mode 100644 index 9294c3d9..00000000 --- a/src/development/secrets/vibetype/api-notification.secret +++ /dev/null @@ -1 +0,0 @@ -vibetype \ No newline at end of file diff --git a/src/development/secrets/vibetype/aws-credentials.secret b/src/development/secrets/vibetype/aws-credentials.secret deleted file mode 100644 index 6075c4fb..00000000 --- a/src/development/secrets/vibetype/aws-credentials.secret +++ /dev/null @@ -1 +0,0 @@ -UNSET THIRD PARTY SECRET \ No newline at end of file diff --git a/src/development/secrets/vibetype/firebase-service-account-credentials.secret b/src/development/secrets/vibetype/firebase-service-account-credentials.secret deleted file mode 100644 index 6075c4fb..00000000 --- a/src/development/secrets/vibetype/firebase-service-account-credentials.secret +++ /dev/null @@ -1 +0,0 @@ -UNSET THIRD PARTY SECRET \ No newline at end of file diff --git a/src/development/secrets/vibetype/monday.secret b/src/development/secrets/vibetype/monday.secret deleted file mode 100644 index 6075c4fb..00000000 --- a/src/development/secrets/vibetype/monday.secret +++ /dev/null @@ -1 +0,0 @@ -UNSET THIRD PARTY SECRET \ No newline at end of file diff --git a/src/development/secrets/vibetype/openai-api-key.secret b/src/development/secrets/vibetype/openai-api-key.secret deleted file mode 100644 index 6075c4fb..00000000 --- a/src/development/secrets/vibetype/openai-api-key.secret +++ /dev/null @@ -1 +0,0 @@ -UNSET THIRD PARTY SECRET \ No newline at end of file diff --git a/src/development/secrets/vibetype/turnstile-key.secret b/src/development/secrets/vibetype/turnstile-key.secret deleted file mode 100644 index d8c28c70..00000000 --- a/src/development/secrets/vibetype/turnstile-key.secret +++ /dev/null @@ -1 +0,0 @@ -1x0000000000000000000000000000000AA \ No newline at end of file diff --git a/src/development/sqitch/compose.yaml b/src/development/sqitch/compose.yaml new file mode 100644 index 00000000..0771a323 --- /dev/null +++ b/src/development/sqitch/compose.yaml @@ -0,0 +1,29 @@ +secrets: + sqitch-target: + # The database change management application's database connection string. + file: ../../../artifacts/secrets/sqitch-target.secret +services: + sqitch: + # You cannot access the database migrations directly. + deploy: + labels: + - dargstack.development.build=../../../../sqitch + - dargstack.profiles=default + image: vibetype/sqitch:development + secrets: + - postgres-role-service-grafana-password + - postgres-role-service-grafana-username + - postgres-role-service-postgraphile-password + - postgres-role-service-postgraphile-username + - postgres-role-service-vibetype-password + - postgres-role-service-vibetype-username + - postgres-role-service-zammad-username + - postgres-role-service-zammad-password + - sqitch-target + volumes: + - ../../../../sqitch/:/srv/app/ +x-dargstack: + secrets: + sqitch-target: + type: template + template: postgres://{{secret:postgres-user}}:{{secret:postgres-password}}@postgres:5432/{{secret:postgres-db}} diff --git a/src/development/secrets/sqitch/target.secret.template b/src/development/sqitch/secrets/target.secret.template similarity index 100% rename from src/development/secrets/sqitch/target.secret.template rename to src/development/sqitch/secrets/target.secret.template diff --git a/src/development/stack.env.template b/src/development/stack.env.template deleted file mode 100644 index 261fdee5..00000000 --- a/src/development/stack.env.template +++ /dev/null @@ -1,8 +0,0 @@ -TUSD_BUCKET=vibetype-images -TUSD_ENDPOINT=http://minio:9000 -TUSD_MAX_SIZE=10485760 -TUSD_REGION=eu-central-1 -VIBETYPE_AWS_REGION=eu-central-1 -VIBETYPE_NUXT_PUBLIC_GTAG_ID=G-WMQ1JY99XH -VIBETYPE_NUXT_PUBLIC_TURNSTILE_SITE_KEY=1x00000000000000000000AA -VIBETYPE_NUXT_PUBLIC_VIBETYPE_EMAIL_LIMIT24H=100 \ No newline at end of file diff --git a/src/development/stack.yml b/src/development/stack.yml deleted file mode 100644 index 893fafe1..00000000 --- a/src/development/stack.yml +++ /dev/null @@ -1,745 +0,0 @@ -# vibetype.app -# https://vibetype.app/ -# Vibetype -# https://github.com/maevsi/vibetype/ ---- -x-shared: - zammad-service: - &zammad-service # You can access the helpdesk at [zammad.app.localhost](https://zammad.app.localhost/). - environment: &zammad-environment - ELASTICSEARCH_HOST: elasticsearch - ELASTICSEARCH_SCHEMA: https - ELASTICSEARCH_USER: elastic - MEMCACHE_SERVERS: memcached:11211 - NGINX_SERVER_SCHEME: https - POSTGRESQL_DB: zammad - POSTGRESQL_DB_CREATE: "false" - POSTGRESQL_HOST: postgres - POSTGRESQL_OPTIONS: ?pool=50 - REDIS_URL: redis://redis:6379 - image: ghcr.io/zammad/zammad:6.5.2-90 - secrets: - - source: elasticsearch-password - target: /run/environment-variables/ELASTICSEARCH_PASS - - source: postgres_role_service_zammad_username - target: /run/environment-variables/POSTGRESQL_USER - - source: postgres_role_service_zammad_password - target: /run/environment-variables/POSTGRESQL_PASS - volumes: - - zammad_data:/opt/zammad/storage - - ../production/configurations/zammad/docker-entrypoint.sh:/docker-entrypoint.sh:ro -secrets: - elasticsearch-keystore_password: - # The search engine's password for the keystore. - file: ./secrets/elasticsearch/keystore_password.secret - elasticsearch-password: - # The search engine's password for the default user. - file: ./secrets/elasticsearch/password.secret - grafana_admin_email: - # The observation dashboard's admin email. - file: ./secrets/grafana/admin_email.secret - grafana_admin_password: - # The observation dashboard's admin password. - file: ./secrets/grafana/admin_password.secret - grafana_admin_user: - # The observation dashboard's admin user. - file: ./secrets/grafana/admin_user.secret - grafana_discord_webhook: - # The observation dashboard's contact point for Discord. - file: ./secrets/grafana/discord_webhook.secret - jobber_aliases: - # The job scheduler's SMTP client mail alias. - file: ./secrets/jobber/aliases.secret - jobber_aws-bucket: - # The job scheduler's AWS bucket name. - file: ./secrets/jobber/aws-bucket.secret - jobber_aws-credentials: - # The job scheduler's AWS credentials. - file: ./secrets/jobber/aws-credentials.secret - jobber_aws-configuration: - # The job scheduler's AWS configuration. - file: ./secrets/jobber/aws-configuration.secret - jobber_msmtprc: - # The job scheduler's SMTP client configuration. - file: ./secrets/jobber/msmtprc.secret - portainer_admin-password: - # The container manager's admin password. - file: ./secrets/portainer/admin-password.secret - postgraphile_connection: - # The GraphQL API's database URI. - file: ./secrets/postgraphile/connection.secret - postgraphile_jwt-secret: - # The GraphQL API's JWT secret. - file: ./secrets/postgraphile/jwt-secret.secret - postgraphile_owner-connection: - # The GraphQL API's database owner URI. - file: ./secrets/postgraphile/owner-connection.secret - postgres_db: - # The database's name. - file: ./secrets/postgres/db.secret - postgres_password: - # The database's password. - file: ./secrets/postgres/password.secret - postgres_role_service_grafana_password: - # The password of the observation dashboard's database role. - file: ./secrets/postgres/role_service_grafana_password.secret - postgres_role_service_grafana_username: - # The username of the observation dashboard's database role. - file: ./secrets/postgres/role_service_grafana_username.secret - postgres_role_service_postgraphile_password: - # The password of the GraphQL API database wrapper's database role. - file: ./secrets/postgres/role_service_postgraphile_password.secret - postgres_role_service_postgraphile_username: - # The username of the GraphQL API database wrapper's database role. - file: ./secrets/postgres/role_service_postgraphile_username.secret - postgres_role_service_vibetype_password: - # The `tusd` database role's password. - file: ./secrets/postgres/role_service_vibetype_password.secret - postgres_role_service_vibetype_username: - # The `tusd` database role's password. - file: ./secrets/postgres/role_service_vibetype_username.secret - postgres_role_service_zammad_password: - # The password of the customer service database role. - file: ./secrets/postgres/role_service_zammad_password.secret - postgres_role_service_zammad_username: - # The username of the customer service database role. - file: ./secrets/postgres/role_service_zammad_username.secret - postgres_user: - # The database's default user. - file: ./secrets/postgres/user.secret - reccoom_ingest-api-key: - # The AI provider's API key for the recommendation engine. - file: ./secrets/reccoom/ingest-api-key.secret - reccoom_openai-api-key: - # The AI provider's API key for the recommendation engine. - file: ./secrets/reccoom/openai-api-key.secret - sqitch_target: - # The database change management application's database connection string. - file: ./secrets/sqitch/target.secret - tusd_aws: - # The upload service's s3 credentials file. - file: ./secrets/tusd/aws.secret - vibetype_api-notification-secret: - # The notification endpoint's secret. - file: ./secrets/vibetype/api-notification.secret - vibetype_aws-credentials: - # The cloud computing provider's user credentials. - file: ./secrets/vibetype/aws-credentials.secret - vibetype_firebase-service-account-credentials: - # The notification provider's service account credentials. - file: ./secrets/vibetype/firebase-service-account-credentials.secret - vibetype_monday: - # The project management software's configuration. - file: ./secrets/vibetype/monday.secret - vibetype_openai-api-key: - # The AI provider's API key for the frontend. - file: ./secrets/vibetype/openai-api-key.secret - vibetype_turnstile-key: - # The captcha provider's application key. - file: ./secrets/vibetype/turnstile-key.secret -services: - adminer: - # You can access the database's frontend at [adminer.app.localhost](https://adminer.app.localhost/). - # This information is required for login: - # - # | | | - # | -------- | ------------------- | - # | System | PostgreSQL | - # | Server | postgres | - # | Username | [postgres_user] | - # | Password | [postgres_password] | - # | Database | [postgres_db] | - # - # Values in square brackets are [Docker secrets](https://docs.docker.com/engine/swarm/secrets/). - deploy: - labels: - - traefik.enable=true - - traefik.http.routers.adminer.entryPoints=web - - traefik.http.routers.adminer.middlewares=redirectscheme #DARGSTACK-REMOVE - - traefik.http.routers.adminer.rule=Host(`adminer.${STACK_DOMAIN}`) - - traefik.http.routers.adminer_secure.entryPoints=web-secure - - traefik.http.routers.adminer_secure.rule=Host(`adminer.${STACK_DOMAIN}`) - - traefik.http.routers.adminer_secure.tls.options=mintls13@file #DARGSTACK-REMOVE - - traefik.http.services.adminer.loadbalancer.server.port=8080 - image: adminer:5.4.2-standalone - volumes: - - ../production/configurations/adminer/adminer.css:/var/www/html/adminer.css:ro - debezium: - # You can see how changes in the database end up in the event stream using `redpanda-console`. - environment: - BOOTSTRAP_SERVERS: redpanda:9092 - CONFIG_STORAGE_TOPIC: connect_configs - GROUP_ID: 1 - OFFSET_STORAGE_TOPIC: connect_offsets - STATUS_STORAGE_TOPIC: connect_statuses - # healthcheck: - # test: ["CMD", "curl", "--fail", "--silent", "--show-error", "http://localhost:8083/connectors"] - # interval: 30s - # timeout: 10s - # retries: 3 - # start_period: 20s - image: quay.io/debezium/connect:3.5 - volumes: - - debezium_kafka_configuration:/kafka/config - - debezium_kafka_data:/kafka/data - - debezium_kafka_logs:/kafka/logs - debezium-postgres-connector: - # You can check the database connector's setup logs using `portainer`. - command: /entrypoint.sh - deploy: - restart_policy: - condition: on-failure - entrypoint: sh - image: curlimages/curl:8.18.0 - secrets: - - postgres_db - - postgres_password - - postgres_user - volumes: - - ../production/configurations/debezium-postgres-connector/entrypoint.sh:/entrypoint.sh:ro - elasticsearch: - # You cannot access the search engine via a web interface. - environment: - bootstrap.memory_lock: "true" - discovery.type: single-node - ELASTIC_PASSWORD_FILE: /run/secrets/elasticsearch-password - ES_JAVA_OPTS: -Xms1g -Xmx1g - KEYSTORE_PASSWORD_FILE: /run/secrets/elasticsearch-keystore_password - network.publish_host: elasticsearch - image: elasticsearch:8.19.12 - secrets: - - source: elasticsearch-keystore_password - uid: "1000" - gid: "1000" - mode: 0o400 - - source: elasticsearch-password - uid: "1000" - gid: "1000" - mode: 0o400 - ulimits: - nofile: - soft: 65535 - hard: 65535 - memlock: - soft: -1 - hard: -1 - volumes: - - elasticsearch-configuration:/usr/share/elasticsearch/config - - elasticsearch_data:/usr/share/elasticsearch/data - geoip: - # You cannot access the ip geolocator via a web interface. - image: ghcr.io/observabilitystack/geoip-api:2026-02 - grafana: - # You can access the observation dashboard at [grafana.app.localhost](https://grafana.app.localhost/). - deploy: - labels: - - traefik.enable=true - - traefik.http.routers.grafana.entryPoints=web - - traefik.http.routers.grafana.middlewares=redirectscheme #DARGSTACK-REMOVE - - traefik.http.routers.grafana.rule=Host(`grafana.${STACK_DOMAIN}`) - - traefik.http.routers.grafana_secure.entryPoints=web-secure - - traefik.http.routers.grafana_secure.rule=Host(`grafana.${STACK_DOMAIN}`) - - traefik.http.routers.grafana_secure.tls.options=mintls13@file #DARGSTACK-REMOVE - - traefik.http.services.grafana.loadbalancer.server.port=3000 - environment: - GF_DATABASE_HOST: postgres:5432 - GF_DATABASE_PASSWORD__FILE: /run/secrets/postgres_role_service_grafana_password - GF_DATABASE_TYPE: postgres - GF_DATABASE_USER__FILE: /run/secrets/postgres_role_service_grafana_username - GF_SECURITY_ADMIN_EMAIL__FILE: /run/secrets/grafana_admin_email - GF_SECURITY_ADMIN_PASSWORD__FILE: /run/secrets/grafana_admin_password - GF_SECURITY_ADMIN_USER__FILE: /run/secrets/grafana_admin_user - GF_SERVER_ROOT_URL: https://grafana.${STACK_DOMAIN}/ - image: grafana/grafana:12.4.1 - secrets: - - grafana_admin_email - - grafana_admin_password - - grafana_admin_user - - grafana_discord_webhook - - postgres_db - - postgres_role_service_grafana_password - - postgres_role_service_grafana_username - volumes: - - ../production/configurations/grafana/dashboards:/var/lib/grafana/dashboards:ro - - ../production/configurations/grafana/provisioning:/etc/grafana/provisioning:ro - - grafana_data:/var/lib/grafana - jobber: - # You cannot access the jobber via a web interface. - environment: - AWS_SHARED_CREDENTIALS_FILE: /run/secrets/jobber_aws-credentials - image: ghcr.io/dargmuesli/jobber-aws-msmtp:1.3.0 - secrets: - - source: jobber_aliases - target: /etc/aliases - - jobber_aws-bucket - - jobber_aws-credentials - - source: jobber_aws-configuration - target: /home/jobberuser/.aws/config - - source: jobber_msmtprc - target: /etc/msmtprc - volumes: - - ../production/backups/postgres/:/backups/ - - ./configurations/jobber/.jobber:/home/jobberuser/.jobber:ro - memcached: - # You cannot access the caching system via a web interface. - image: memcached:1.6.41-alpine - # command: memcached -m 256M - minio: #DARGSTACK-REMOVE - # You can access the s3 console at [minio.app.localhost](https://minio.app.localhost/). - # You can access the s3 api service at [s3.app.localhost](https://s3.app.localhost/) if you want to access via cli from outside the stack. - entrypoint: /patched-entrypoint.sh #DARGSTACK-REMOVE - command: server /data --console-address ":9001" #DARGSTACK-REMOVE - deploy: #DARGSTACK-REMOVE - labels: #DARGSTACK-REMOVE - - traefik.enable=true #DARGSTACK-REMOVE - # Minio Console - - traefik.http.routers.minio.entryPoints=web #DARGSTACK-REMOVE - - traefik.http.routers.minio.middlewares=redirectscheme #DARGSTACK-REMOVE - - traefik.http.routers.minio.rule=Host(`minio.${STACK_DOMAIN}`) #DARGSTACK-REMOVE - - traefik.http.routers.minio.service=minio #DARGSTACK-REMOVE - - traefik.http.routers.minio_secure.entryPoints=web-secure #DARGSTACK-REMOVE - - traefik.http.routers.minio_secure.rule=Host(`minio.${STACK_DOMAIN}`) #DARGSTACK-REMOVE - - traefik.http.routers.minio_secure.tls.options=mintls13@file #DARGSTACK-REMOVE - - traefik.http.routers.minio_secure.service=minio #DARGSTACK-REMOVE - - traefik.http.services.minio.loadbalancer.server.port=9001 #DARGSTACK-REMOVE - - traefik.http.services.minio.loadbalancer.passhostheader=true #DARGSTACK-REMOVE - # Minio itself - - traefik.http.routers.s3.entryPoints=web #DARGSTACK-REMOVE - - traefik.http.routers.s3.middlewares=redirectscheme #DARGSTACK-REMOVE - - traefik.http.routers.s3.rule=Host(`s3.${STACK_DOMAIN}`) #DARGSTACK-REMOVE - - traefik.http.routers.s3.service=s3 #DARGSTACK-REMOVE - - traefik.http.routers.s3_secure.entryPoints=web-secure #DARGSTACK-REMOVE - - traefik.http.routers.s3_secure.rule=Host(`s3.${STACK_DOMAIN}`) #DARGSTACK-REMOVE - - traefik.http.routers.s3_secure.tls.options=mintls13@file #DARGSTACK-REMOVE - - traefik.http.routers.s3_secure.service=s3 #DARGSTACK-REMOVE - - traefik.http.services.s3.loadbalancer.server.port=9000 #DARGSTACK-REMOVE - - traefik.http.services.s3.loadbalancer.passhostheader=true #DARGSTACK-REMOVE - image: minio/minio #DARGSTACK-REMOVE - volumes: #DARGSTACK-REMOVE - - minio_data:/data #DARGSTACK-REMOVE - - ./configurations/minio/entrypoint.sh:/patched-entrypoint.sh #DARGSTACK-REMOVE - environment: #DARGSTACK-REMOVE - MINIO_ROOT_PASSWORD: s3password #DARGSTACK-REMOVE - MINIO_ROOT_USER: s3user #DARGSTACK-REMOVE - portainer: - # You can access the container manager's frontend at [portainer.app.localhost](https://portainer.app.localhost/). - command: -H tcp://tasks.portainer-agent:9001 --tlsskipverify --admin-password-file '/run/secrets/portainer_admin-password' - deploy: - labels: - - traefik.enable=true - - traefik.http.routers.portainer.entryPoints=web - - traefik.http.routers.portainer.middlewares=redirectscheme #DARGSTACK-REMOVE - - traefik.http.routers.portainer.rule=Host(`portainer.${STACK_DOMAIN}`) - - traefik.http.routers.portainer_secure.entryPoints=web-secure - - traefik.http.routers.portainer_secure.rule=Host(`portainer.${STACK_DOMAIN}`) - - traefik.http.routers.portainer_secure.tls.options=mintls13@file #DARGSTACK-REMOVE - - traefik.http.services.portainer.loadbalancer.server.port=9000 - placement: - constraints: - - node.role == manager - replicas: 1 - image: portainer/portainer-ce:2.39.0-alpine - secrets: - - portainer_admin-password - volumes: - - portainer_data:/data - portainer-agent: - # You cannot access the container manager's agent directly. - deploy: - mode: global - placement: - constraints: - - node.platform.os == linux - image: portainer/agent:2.39.0 - volumes: - - /var/run/docker.sock:/var/run/docker.sock - - /var/lib/docker/volumes:/var/lib/docker/volumes - postgraphile: - # You can access the GraphQL API for the PostgreSQL database at [postgraphile.app.localhost](https://postgraphile.app.localhost/). - deploy: - labels: - - traefik.enable=true - - traefik.http.middlewares.postgraphile_auth.forwardauth.address=http://vibetype:3000/api/internal/service/postgraphile/authentication - - traefik.http.middlewares.postgraphile_auth.forwardauth.forwardBody=true - - traefik.http.middlewares.postgraphile_auth.forwardauth.preserveRequestMethod=true - - traefik.http.middlewares.postgraphile_cors.headers.accessControlAllowCredentials=true - - traefik.http.middlewares.postgraphile_cors.headers.accessControlAllowHeaders=authorization - - traefik.http.middlewares.postgraphile_cors.headers.accessControlAllowOriginList=https://${STACK_DOMAIN},https://localhost:3000,https://app.localhost:3000 - - traefik.http.routers.postgraphile.entryPoints=web - - traefik.http.routers.postgraphile.middlewares=redirectscheme #DARGSTACK-REMOVE - - traefik.http.routers.postgraphile.rule=Host(`postgraphile.${STACK_DOMAIN}`) - - traefik.http.routers.postgraphile_secure.entryPoints=web-secure - - traefik.http.routers.postgraphile_secure.middlewares=postgraphile_auth,postgraphile_cors - - traefik.http.routers.postgraphile_secure.rule=Host(`postgraphile.${STACK_DOMAIN}`) && Path(`/graphql`) - - traefik.http.routers.postgraphile_secure.tls.options=mintls13@file #DARGSTACK-REMOVE - - traefik.http.routers.postgraphile_secure_graphiql.entryPoints=web-secure - - traefik.http.routers.postgraphile_secure_graphiql.rule=Host(`postgraphile.${STACK_DOMAIN}`) - - traefik.http.routers.postgraphile_secure_graphiql.tls.options=mintls13@file #DARGSTACK-REMOVE - - traefik.http.services.postgraphile.loadbalancer.server.port=5678 - # # Use the DEBUG environment variable for extended debugging. - # environment: - # DEBUG: graphile-build:warn,graphile-build-pg:sql - image: maevsi/postgraphile:dev - secrets: - - source: postgraphile_connection - target: /run/environment-variables/POSTGRAPHILE_CONNECTION - - source: postgraphile_jwt-secret - target: /run/environment-variables/POSTGRAPHILE_JWT_SECRET_KEY - - source: postgraphile_owner-connection - target: /run/environment-variables/POSTGRAPHILE_OWNER_CONNECTION - volumes: - - ../../../postgraphile/:/srv/app/ #DARGSTACK-REMOVE - - ./configurations/postgraphile/jwtRS256.key.pub:/run/environment-variables/POSTGRAPHILE_JWT_PUBLIC_KEY:ro - - pnpm_data:/srv/.pnpm-store/ #DARGSTACK-REMOVE - - postgraphile_data:/srv/app/node_modules #DARGSTACK-REMOVE - postgres: - # You can access the database via `adminer`. - command: -c vibetype.jwt_expiry_duration='1 month' -c wal_level=logical - environment: - POSTGRES_DB_FILE: /run/secrets/postgres_db - POSTGRES_PASSWORD_FILE: /run/secrets/postgres_password - POSTGRES_USER_FILE: /run/secrets/postgres_user - image: postgis/postgis:18-3.6-alpine - ports: #DARGSTACK-REMOVE - - 5432:5432 #DARGSTACK-REMOVE - secrets: - - postgres_db - - postgres_password - - postgres_user - # sysctls: - # # Prevent Docker Swarm from killing connections (https://github.com/moby/moby/issues/31208) - # - net.ipv4.tcp_keepalive_time=600 - # - net.ipv4.tcp_keepalive_intvl=30 - # - net.ipv4.tcp_keepalive_probes=10 - volumes: - - postgres_data:/var/lib/postgresql/ - prometheus: - # You can access the metrics monitoring at [prometheus.app.localhost](https://prometheus.app.localhost/). - deploy: - labels: - - traefik.enable=true - - traefik.http.routers.prometheus.entryPoints=web - - traefik.http.routers.prometheus.middlewares=redirectscheme #DARGSTACK-REMOVE - - traefik.http.routers.prometheus.rule=Host(`prometheus.${STACK_DOMAIN}`) - - traefik.http.routers.prometheus_secure.entryPoints=web-secure - - traefik.http.routers.prometheus_secure.rule=Host(`prometheus.${STACK_DOMAIN}`) - - traefik.http.routers.prometheus_secure.tls.options=mintls13@file #DARGSTACK-REMOVE - - traefik.http.services.prometheus.loadbalancer.server.port=9090 - image: prom/prometheus:v3.10.0 - volumes: - - ../production/configurations/prometheus/prometheus.yaml:/etc/prometheus/prometheus.yml:ro - - prometheus_data:/prometheus - reccoom: - # You cannot access the recommendation service directly. - deploy: - labels: - - traefik.enable=true - - traefik.http.routers.reccoom.entryPoints=web - - traefik.http.routers.reccoom.middlewares=redirectscheme #DARGSTACK-REMOVE - - traefik.http.routers.reccoom.rule=Host(`reccoom.${STACK_DOMAIN}`) - - traefik.http.routers.reccoom_secure.entryPoints=web-secure - - traefik.http.routers.reccoom_secure.rule=Host(`reccoom.${STACK_DOMAIN}`) - - traefik.http.routers.reccoom_secure.tls.options=mintls13@file #DARGSTACK-REMOVE - - traefik.http.services.reccoom.loadbalancer.server.port=5245 - environment: - POSTGRES_HOST: postgres - RECCOOM_POSTGRES_HOST: reccoom_postgres - image: maevsi/reccoom:dev - secrets: - - postgres_db - - postgres_password - - postgres_user - - source: reccoom_ingest-api-key - target: /run/environment-variables/INGEST_API_KEY - - reccoom_openai-api-key - volumes: - - ../../../reccoom/:/srv/app/ #DARGSTACK-REMOVE - - ./configurations/postgraphile/jwtRS256.key.pub:/run/configurations/jwtRS256.key.pub:ro - reccoom_postgres: - # You can access reccoom's database via `adminer`. - environment: - POSTGRES_DB_FILE: /run/secrets/postgres_db - POSTGRES_PASSWORD_FILE: /run/secrets/postgres_password - POSTGRES_USER_FILE: /run/secrets/postgres_user - image: pgvector/pgvector:0.8.2-pg18 - ports: #DARGSTACK-REMOVE - - 5433:5432 #DARGSTACK-REMOVE - secrets: - - postgres_db - - postgres_password - - postgres_user - volumes: - - reccoom_postgres_data:/var/lib/postgresql/ - redis: - # You cannot access the caching system via a web interface. - image: redis:8.6.1-alpine - volumes: - - redis_data:/data - redpanda: - # You can access the event streaming platform's ui as described under `redpanda-console`. - command: - - redpanda start - - --mode dev-container #DARGSTACK-REMOVE - - --kafka-addr internal://0.0.0.0:9092,external://0.0.0.0:19092 - - --advertise-kafka-addr internal://redpanda:9092,external://localhost:19092 - - --pandaproxy-addr internal://0.0.0.0:8082,external://0.0.0.0:18082 - - --advertise-pandaproxy-addr internal://redpanda:8082,external://localhost:18082 - - --schema-registry-addr internal://0.0.0.0:8081,external://0.0.0.0:18081 - # healthcheck: - # test: ["CMD-SHELL", "output=$(rpk cluster health --json); echo \"$output\" | grep -q '\"healthy\":true' || { echo \"$output\"; exit 1; }"] - # interval: 30s - # timeout: 10s - # retries: 3 - # start_period: 10s - image: redpandadata/redpanda:v25.3.10 - volumes: - - redpanda_data:/var/lib/redpanda/data - redpanda-console: - # You can access the event streaming platform's ui at [redpanda.app.localhost](https://redpanda.app.localhost/). - deploy: - labels: - - traefik.enable=true - - traefik.http.routers.redpanda.entryPoints=web - - traefik.http.routers.redpanda.middlewares=redirectscheme #DARGSTACK-REMOVE - - traefik.http.routers.redpanda.rule=Host(`redpanda.${STACK_DOMAIN}`) - - traefik.http.routers.redpanda_secure.entryPoints=web-secure - - traefik.http.routers.redpanda_secure.rule=Host(`redpanda.${STACK_DOMAIN}`) - - traefik.http.routers.redpanda_secure.tls.options=mintls13@file #DARGSTACK-REMOVE - - traefik.http.services.redpanda.loadbalancer.server.port=8080 - environment: - CONFIG_FILEPATH: /srv/app/redpanda-config.yaml - image: redpandadata/console:v3.5.3 - volumes: - - ../production/configurations/redpanda/config.yaml:/srv/app/redpanda-config.yaml:ro - sqitch: - # You cannot access the database migrations directly. - image: maevsi/sqitch:dev - secrets: - - postgres_role_service_grafana_password - - postgres_role_service_grafana_username - - postgres_role_service_postgraphile_password - - postgres_role_service_postgraphile_username - - postgres_role_service_vibetype_password - - postgres_role_service_vibetype_username - - postgres_role_service_zammad_username - - postgres_role_service_zammad_password - - sqitch_target - volumes: - - ../../../sqitch/:/srv/app/ - traefik: - # You can access the reverse proxy's dashboard at [traefik.app.localhost](https://traefik.app.localhost/). - command: - - --api=true - - --entryPoints.web.address=:80 - - --entryPoints.web-secure.address=:443 - - --entryPoints.web-secure.http.encodedCharacters.allowEncodedSlash=true #DARGSTACK-REMOVE # required for Nuxt's virtual imports - - --providers.swarm=true - - --providers.swarm.endpoint=unix:///var/run/docker.sock - - --providers.swarm.exposedByDefault=false - - --providers.file.filename=/dynamic.yml #DARGSTACK-REMOVE - - --providers.file.watch=true #DARGSTACK-REMOVE - - --log.level=DEBUG #DARGSTACK-REMOVE - deploy: - labels: - - traefik.enable=true - - traefik.http.middlewares.redirectscheme.redirectscheme.scheme=https #DARGSTACK-REMOVE - - traefik.http.routers.traefik.entryPoints=web - - traefik.http.routers.traefik.middlewares=redirectscheme #DARGSTACK-REMOVE - - traefik.http.routers.traefik.rule=Host(`traefik.${STACK_DOMAIN}`) - - traefik.http.routers.traefik.service=api@internal - - traefik.http.routers.traefik_secure.entryPoints=web-secure - - traefik.http.routers.traefik_secure.rule=Host(`traefik.${STACK_DOMAIN}`) - - traefik.http.routers.traefik_secure.service=api@internal - - traefik.http.routers.traefik_secure.tls.options=mintls13@file #DARGSTACK-REMOVE - - traefik.http.services.traefik.loadbalancer.server.port=8080 - mode: global - placement: - constraints: - - node.role == manager - image: traefik:v3.6.10 - ports: #DARGSTACK-REMOVE - - mode: host #DARGSTACK-REMOVE - protocol: tcp #DARGSTACK-REMOVE - published: 80 #DARGSTACK-REMOVE - target: 80 #DARGSTACK-REMOVE - - mode: host #DARGSTACK-REMOVE - protocol: tcp #DARGSTACK-REMOVE - published: 443 #DARGSTACK-REMOVE - target: 443 #DARGSTACK-REMOVE - volumes: - - /var/run/docker.sock:/var/run/docker.sock - - ./certificates/:/etc/traefik/acme/ - - ./configurations/traefik/dynamic.yml:/dynamic.yml:ro #DARGSTACK-REMOVE - tusd: - # You can access the upload service at [tusd.app.localhost](https://tusd.app.localhost/). - command: -behind-proxy --hooks-enabled-events pre-create,pre-finish,pre-terminate --hooks-http http://vibetype:3000/api/internal/service/tusd -max-size ${TUSD_MAX_SIZE} -s3-bucket ${TUSD_BUCKET} -s3-endpoint ${TUSD_ENDPOINT} - deploy: - labels: - - traefik.enable=true - - traefik.http.middlewares.tusd_cors.headers.customresponseheaders.Cross-Origin-Resource-Policy=cross-origin - - traefik.http.routers.tusd.entryPoints=web - - traefik.http.routers.tusd.middlewares=redirectscheme #DARGSTACK-REMOVE - - traefik.http.routers.tusd.rule=Host(`tusd.${STACK_DOMAIN}`) - - traefik.http.routers.tusd_secure.entryPoints=web-secure - - traefik.http.routers.tusd_secure.middlewares=tusd_cors - - traefik.http.routers.tusd_secure.rule=Host(`tusd.${STACK_DOMAIN}`) && (Method(`GET`) || Method(`HEAD`) || Method(`OPTIONS`) || Method(`POST`) || Method(`PUT`) || Method(`PATCH`)) - - traefik.http.routers.tusd_secure.tls.options=mintls13@file #DARGSTACK-REMOVE - - traefik.http.services.tusd.loadbalancer.server.port=8080 - environment: - AWS_REGION: ${TUSD_REGION} - image: tusproject/tusd:v2.9.1 - secrets: - - source: tusd_aws - target: /home/tusd/.aws/credentials - vibetype: - # You can access the main project's frontend at [app.localhost](https://app.localhost/). - deploy: - labels: - - traefik.enable=true - - traefik.http.middlewares.vibetype_cors.headers.accessControlAllowHeaders=authorization,content-type,hook-name,x-turnstile-key - - traefik.http.middlewares.vibetype_cors.headers.accessControlAllowMethods=GET,POST,PUT,DELETE - - traefik.http.middlewares.vibetype_cors.headers.accessControlAllowOriginList=https://localhost:3000,https://app.localhost:3000 - - traefik.http.middlewares.vibetype_redirectregex.redirectregex.regex=^https?:\/\/www\.${STACK_DOMAIN}\/(.*) - - traefik.http.middlewares.vibetype_redirectregex.redirectregex.replacement=https://${STACK_DOMAIN}/$${2} - - traefik.http.routers.vibetype.entryPoints=web - - traefik.http.routers.vibetype.middlewares=redirectscheme #DARGSTACK-REMOVE - - traefik.http.routers.vibetype.rule=(Host(`${STACK_DOMAIN}`) || Host(`www.${STACK_DOMAIN}`)) && !PathPrefix(`/api/internal`) - - traefik.http.routers.vibetype_secure.entryPoints=web-secure - - traefik.http.routers.vibetype_secure.middlewares=vibetype_cors,vibetype_redirectregex - - traefik.http.routers.vibetype_secure.rule=(Host(`${STACK_DOMAIN}`) || Host(`www.${STACK_DOMAIN}`)) && !PathPrefix(`/api/internal`) - - traefik.http.routers.vibetype_secure.tls.options=mintls13@file #DARGSTACK-REMOVE - - traefik.http.services.vibetype.loadbalancer.server.port=3000 - environment: - AWS_REGION: ${VIBETYPE_AWS_REGION} - NUXT_PUBLIC_GTAG_ID: ${VIBETYPE_NUXT_PUBLIC_GTAG_ID} - NUXT_PUBLIC_I18N_BASE_URL: https://${STACK_DOMAIN} - NUXT_PUBLIC_SITE_URL: https://${STACK_DOMAIN} - NUXT_PUBLIC_TURNSTILE_SITE_KEY: ${VIBETYPE_NUXT_PUBLIC_TURNSTILE_SITE_KEY} - NUXT_PUBLIC_VIBETYPE_EMAIL_LIMIT24H: ${VIBETYPE_NUXT_PUBLIC_VIBETYPE_EMAIL_LIMIT24H} - PGHOST: postgres - image: maevsi/vibetype:dev - secrets: - - source: vibetype_api-notification-secret - target: /run/environment-variables/NUXT_PRIVATE_API_NOTIFICATION_SECRET - - source: vibetype_aws-credentials - target: /home/node/.aws/credentials - - source: vibetype_firebase-service-account-credentials - target: /run/environment-variables/FIREBASE_SERVICE_ACCOUNT_CREDENTIALS - - source: vibetype_monday - target: /run/environment-variables/NUXT_PRIVATE_MONDAY - - source: vibetype_openai-api-key - target: /run/environment-variables/NUXT_PRIVATE_OPENAI_API_KEY - - source: vibetype_turnstile-key - target: /run/environment-variables/NUXT_TURNSTILE_SECRET_KEY - - source: postgres_db - target: /run/environment-variables/PGDATABASE - - source: postgres_role_service_vibetype_password - target: /run/environment-variables/PGPASSWORD - - source: postgres_role_service_vibetype_username - target: /run/environment-variables/PGUSER - user: node:node # files created inside a docker container, like node_modules by pnpm, gain correct permissions by setting the user to `node` - volumes: - - pnpm_data:/srv/.pnpm-store/ #DARGSTACK-REMOVE - - ./certificates/:/srv/certificates/ #DARGSTACK-REMOVE - - ../../../vibetype/:/srv/app/ #DARGSTACK-REMOVE - - vibetype_data:/srv/app/node_modules #DARGSTACK-REMOVE - - ./configurations/postgraphile/jwtRS256.key.pub:/run/environment-variables/NUXT_PUBLIC_VIO_AUTH_JWT_PUBLIC_KEY:ro - zammad-backup: - # You cannot access the helpdesk backup service via a web interface. - <<: *zammad-service - command: ["zammad-backup"] - user: 0:0 - volumes: - - zammad-backup_data:/var/tmp/zammad - - zammad_data:/opt/zammad/storage:ro - - ../production/configurations/zammad/docker-entrypoint.sh:/docker-entrypoint.sh:ro - zammad-init: - # You cannot access the helpdesk initialization service via a web interface. - <<: *zammad-service - command: ["zammad-init"] - deploy: - restart_policy: - condition: on-failure - user: 0:0 - zammad-nginx: - # You can access the helpdesk at [zammad.app.localhost](https://zammad.app.localhost/). - <<: *zammad-service - command: ["zammad-nginx"] - deploy: - labels: - - traefik.enable=true - - traefik.http.routers.zammad.entryPoints=web - - traefik.http.routers.zammad.middlewares=redirectscheme #DARGSTACK-REMOVE - - traefik.http.routers.zammad.rule=Host(`zammad.${STACK_DOMAIN}`) - - traefik.http.routers.zammad_secure.entryPoints=web-secure - - traefik.http.routers.zammad_secure.rule=Host(`zammad.${STACK_DOMAIN}`) - - traefik.http.routers.zammad_secure.tls.options=mintls13@file #DARGSTACK-REMOVE - - traefik.http.services.zammad.loadbalancer.server.port=8080 - zammad-railsserver: - # You cannot access the helpdesk application server directly. - <<: *zammad-service - command: ["zammad-railsserver"] - zammad-scheduler: - # You cannot access the helpdesk scheduler directly. - <<: *zammad-service - command: ["zammad-scheduler"] - zammad-websocket: - # You cannot access the helpdesk websocket server directly. - <<: *zammad-service - command: ["zammad-websocket"] -version: "3.7" -volumes: - debezium_kafka_configuration: - # The change data capture's configuration. - {} - debezium_kafka_data: - # The change data capture's data. - {} - debezium_kafka_logs: - # The change data capture's logs. - {} - elasticsearch-configuration: - # The search engine's configuration. - {} - elasticsearch_data: - # The search engine's data. - {} - grafana_data: - # The observation dashboard's data. - {} - minio_data: - # The s3 server's data. - {} - pnpm_data: - # The node package manager's data. - {} - portainer_data: - # The container manager's data. - {} - postgraphile_data: - # The GraphQL API's data. - {} - postgres_data: - # The database's data. - {} - prometheus_data: - # The metrics monitoring's data. - {} - reccoom_postgres_data: - # The recommendation database's data. - {} - redis_data: - # The caching system's data. - {} - redpanda_data: - # The message queue's data. - {} - vibetype_data: - # The frontend's data. - {} - zammad-backup_data: - # The helpdesk backup's data. - {} - zammad_data: - # The helpdesk's data. - {} diff --git a/src/development/traefik/compose.yaml b/src/development/traefik/compose.yaml new file mode 100644 index 00000000..a93c1d99 --- /dev/null +++ b/src/development/traefik/compose.yaml @@ -0,0 +1,46 @@ +services: + traefik: + # You can access the reverse proxy's dashboard at [traefik.app.localhost](https://traefik.app.localhost/). + command: + - --api=true + - --entryPoints.web.address=:80 + - --entryPoints.web-secure.address=:443 + - --entryPoints.web-secure.http.encodedCharacters.allowEncodedSlash=true # dargstack:dev-only # required for Nuxt's virtual imports + - --providers.swarm=true + - --providers.swarm.endpoint=unix:///var/run/docker.sock + - --providers.swarm.exposedByDefault=false + - --providers.file.filename=/dynamic.yml # dargstack:dev-only + - --providers.file.watch=true # dargstack:dev-only + - --log.level=DEBUG # dargstack:dev-only + deploy: + labels: + - dargstack.profiles=default + - traefik.enable=true + - traefik.http.middlewares.redirectscheme.redirectscheme.scheme=https # dargstack:dev-only + - traefik.http.routers.traefik.entryPoints=web + - traefik.http.routers.traefik.middlewares=redirectscheme # dargstack:dev-only + - traefik.http.routers.traefik.rule=Host(`traefik.${STACK_DOMAIN}`) + - traefik.http.routers.traefik.service=api@internal + - traefik.http.routers.traefik-secure.entryPoints=web-secure + - traefik.http.routers.traefik-secure.rule=Host(`traefik.${STACK_DOMAIN}`) + - traefik.http.routers.traefik-secure.service=api@internal + - traefik.http.routers.traefik-secure.tls.options=mintls13@file # dargstack:dev-only + - traefik.http.services.traefik.loadbalancer.server.port=8080 + mode: global + placement: + constraints: + - node.role == manager + image: traefik:v3.6.10 + ports: # dargstack:dev-only + - mode: host # dargstack:dev-only + protocol: tcp # dargstack:dev-only + published: 80 # dargstack:dev-only + target: 80 # dargstack:dev-only + - mode: host # dargstack:dev-only + protocol: tcp # dargstack:dev-only + published: 443 # dargstack:dev-only + target: 443 # dargstack:dev-only + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - ../../../artifacts/certificates/:/etc/traefik/acme/ + - ./configurations/dynamic.yml:/dynamic.yml:ro # dargstack:dev-only diff --git a/src/development/traefik/configurations/dynamic.yml b/src/development/traefik/configurations/dynamic.yml new file mode 100644 index 00000000..705f4828 --- /dev/null +++ b/src/development/traefik/configurations/dynamic.yml @@ -0,0 +1,7 @@ +tls: + certificates: + - certFile: /etc/traefik/acme/localhost.pem + keyFile: /etc/traefik/acme/localhost-key.pem + options: + mintls13: + minVersion: VersionTLS13 diff --git a/src/development/tusd/compose.yaml b/src/development/tusd/compose.yaml new file mode 100644 index 00000000..cf1e2233 --- /dev/null +++ b/src/development/tusd/compose.yaml @@ -0,0 +1,35 @@ +secrets: + tusd-aws: + # The upload service's s3 credentials file. + file: ../../../artifacts/secrets/tusd-aws.secret +services: + tusd: + # You can access the upload service at [tusd.app.localhost](https://tusd.app.localhost/). + command: -behind-proxy --hooks-enabled-events pre-create,pre-finish,pre-terminate --hooks-http http://vibetype:3000/api/internal/service/tusd -max-size ${TUSD_MAX_SIZE} -s3-bucket ${TUSD_BUCKET} -s3-endpoint ${TUSD_ENDPOINT} + deploy: + labels: + - dargstack.profiles=upload + - traefik.enable=true + - traefik.http.middlewares.tusd-cors.headers.customresponseheaders.Cross-Origin-Resource-Policy=cross-origin + - traefik.http.routers.tusd.entryPoints=web + - traefik.http.routers.tusd.middlewares=redirectscheme # dargstack:dev-only + - traefik.http.routers.tusd.rule=Host(`tusd.${STACK_DOMAIN}`) + - traefik.http.routers.tusd-secure.entryPoints=web-secure + - traefik.http.routers.tusd-secure.middlewares=tusd-cors + - traefik.http.routers.tusd-secure.rule=Host(`tusd.${STACK_DOMAIN}`) && (Method(`GET`) || Method(`HEAD`) || Method(`OPTIONS`) || Method(`POST`) || Method(`PUT`) || Method(`PATCH`)) + - traefik.http.routers.tusd-secure.tls.options=mintls13@file # dargstack:dev-only + - traefik.http.services.tusd.loadbalancer.server.port=8080 + environment: + AWS_REGION: ${TUSD_REGION} + image: tusproject/tusd:v2.9.1 + secrets: + - source: tusd-aws + target: /home/tusd/.aws/credentials +x-dargstack: + secrets: + tusd-aws: + insecure_default: | + [default] + aws_access_key_id = s3user + aws_secret_access_key = s3password + type: insecure_default diff --git a/src/development/secrets/tusd/aws.secret.template b/src/development/tusd/secrets/aws.secret.template similarity index 100% rename from src/development/secrets/tusd/aws.secret.template rename to src/development/tusd/secrets/aws.secret.template diff --git a/src/development/vibetype/compose.yaml b/src/development/vibetype/compose.yaml new file mode 100644 index 00000000..a2c12f8f --- /dev/null +++ b/src/development/vibetype/compose.yaml @@ -0,0 +1,93 @@ +secrets: + vibetype-api-notification-secret: + # The notification endpoint's secret. + file: ../../../artifacts/secrets/vibetype-api-notification.secret + vibetype-aws-credentials: + # The cloud computing provider's user credentials. + file: ../../../artifacts/secrets/vibetype-aws-credentials.secret + vibetype-firebase-service-account-credentials: + # The notification provider's service account credentials. + file: ../../../artifacts/secrets/vibetype-firebase-service-account-credentials.secret + vibetype-monday: + # The project management software's configuration. + file: ../../../artifacts/secrets/vibetype-monday.secret + vibetype-openai-api-key: + # The AI provider's API key for the frontend. + file: ../../../artifacts/secrets/vibetype-openai-api-key.secret + vibetype-turnstile-key: + # The captcha provider's application key. + file: ../../../artifacts/secrets/vibetype-turnstile-key.secret +services: + vibetype: + # You can access the main project's frontend at [app.localhost](https://app.localhost/). + deploy: + labels: + - dargstack.development.build=../../../../vibetype + - dargstack.profiles=default + - traefik.enable=true + - traefik.http.middlewares.vibetype-cors.headers.accessControlAllowHeaders=authorization,content-type,hook-name,x-turnstile-key + - traefik.http.middlewares.vibetype-cors.headers.accessControlAllowMethods=GET,POST,PUT,DELETE + - traefik.http.middlewares.vibetype-cors.headers.accessControlAllowOriginList=https://localhost:3000,https://app.localhost:3000 + - traefik.http.middlewares.vibetype-redirectregex.redirectregex.regex=^https?:\/\/www\.${STACK_DOMAIN}\/(.*) + - traefik.http.middlewares.vibetype-redirectregex.redirectregex.replacement=https://${STACK_DOMAIN}/$${1} + - traefik.http.routers.vibetype.entryPoints=web + - traefik.http.routers.vibetype.middlewares=redirectscheme # dargstack:dev-only + - traefik.http.routers.vibetype.rule=(Host(`${STACK_DOMAIN}`) || Host(`www.${STACK_DOMAIN}`)) && !PathPrefix(`/api/internal`) + - traefik.http.routers.vibetype-secure.entryPoints=web-secure + - traefik.http.routers.vibetype-secure.middlewares=vibetype-cors,vibetype-redirectregex + - traefik.http.routers.vibetype-secure.rule=(Host(`${STACK_DOMAIN}`) || Host(`www.${STACK_DOMAIN}`)) && !PathPrefix(`/api/internal`) + - traefik.http.routers.vibetype-secure.tls.options=mintls13@file # dargstack:dev-only + - traefik.http.services.vibetype.loadbalancer.server.port=3000 + environment: + AWS_REGION: ${VIBETYPE_AWS_REGION} + NUXT_PUBLIC_GTAG_ID: ${VIBETYPE_NUXT_PUBLIC_GTAG_ID} + NUXT_PUBLIC_I18N_BASE_URL: https://${STACK_DOMAIN} + NUXT_PUBLIC_SITE_URL: https://${STACK_DOMAIN} + NUXT_PUBLIC_TURNSTILE_SITE_KEY: ${VIBETYPE_NUXT_PUBLIC_TURNSTILE_SITE_KEY} + NUXT_PUBLIC_VIBETYPE_EMAIL_LIMIT24H: ${VIBETYPE_NUXT_PUBLIC_VIBETYPE_EMAIL_LIMIT24H} + PGHOST: postgres + image: vibetype/vibetype:development + secrets: + - source: vibetype-api-notification-secret + target: /run/environment-variables/NUXT_PRIVATE_API_NOTIFICATION_SECRET + - source: vibetype-aws-credentials + target: /home/node/.aws/credentials + - source: vibetype-firebase-service-account-credentials + target: /run/environment-variables/FIREBASE_SERVICE_ACCOUNT_CREDENTIALS + - source: vibetype-monday + target: /run/environment-variables/NUXT_PRIVATE_MONDAY + - source: vibetype-openai-api-key + target: /run/environment-variables/NUXT_PRIVATE_OPENAI_API_KEY + - source: vibetype-turnstile-key + target: /run/environment-variables/NUXT_TURNSTILE_SECRET_KEY + - source: postgres-db + target: /run/environment-variables/PGDATABASE + - source: postgres-role-service-vibetype-password + target: /run/environment-variables/PGPASSWORD + - source: postgres-role-service-vibetype-username + target: /run/environment-variables/PGUSER + user: node:node # files created inside a docker container, like node_modules by pnpm, gain correct permissions by setting the user to `node` + volumes: + - pnpm-data:/srv/.pnpm-store/ # dargstack:dev-only + - ../../../artifacts/certificates/:/srv/certificates/ # dargstack:dev-only + - ../../../../vibetype/:/srv/app/ # dargstack:dev-only + - vibetype-data:/srv/app/node_modules # dargstack:dev-only + - ../postgraphile/configurations/jwtRS256.key.pub:/run/environment-variables/NUXT_PUBLIC_VIO_AUTH_JWT_PUBLIC_KEY:ro +volumes: + vibetype-data: + # The frontend's data. + {} +x-dargstack: + secrets: + vibetype-api-notification-secret: + type: random_string + vibetype-aws-credentials: + type: third_party + vibetype-firebase-service-account-credentials: + type: third_party + vibetype-monday: + type: third_party + vibetype-openai-api-key: + type: third_party + vibetype-turnstile-key: + type: third_party diff --git a/src/development/secrets/vibetype/api-notification.secret.template b/src/development/vibetype/secrets/api-notification.secret.template similarity index 100% rename from src/development/secrets/vibetype/api-notification.secret.template rename to src/development/vibetype/secrets/api-notification.secret.template diff --git a/src/development/secrets/vibetype/aws-credentials.secret.template b/src/development/vibetype/secrets/aws-credentials.secret.template similarity index 100% rename from src/development/secrets/vibetype/aws-credentials.secret.template rename to src/development/vibetype/secrets/aws-credentials.secret.template diff --git a/src/development/secrets/vibetype/firebase-service-account-credentials.secret.template b/src/development/vibetype/secrets/firebase-service-account-credentials.secret.template similarity index 100% rename from src/development/secrets/vibetype/firebase-service-account-credentials.secret.template rename to src/development/vibetype/secrets/firebase-service-account-credentials.secret.template diff --git a/src/development/secrets/vibetype/monday.template b/src/development/vibetype/secrets/monday.template similarity index 100% rename from src/development/secrets/vibetype/monday.template rename to src/development/vibetype/secrets/monday.template diff --git a/src/development/secrets/vibetype/openai-api-key.secret.template b/src/development/vibetype/secrets/openai-api-key.secret.template similarity index 100% rename from src/development/secrets/vibetype/openai-api-key.secret.template rename to src/development/vibetype/secrets/openai-api-key.secret.template diff --git a/src/development/secrets/vibetype/turnstile-key.secret.template b/src/development/vibetype/secrets/turnstile-key.secret.template similarity index 100% rename from src/development/secrets/vibetype/turnstile-key.secret.template rename to src/development/vibetype/secrets/turnstile-key.secret.template diff --git a/src/development/zammad/compose.yaml b/src/development/zammad/compose.yaml new file mode 100644 index 00000000..e3f1f6d7 --- /dev/null +++ b/src/development/zammad/compose.yaml @@ -0,0 +1,82 @@ +x-shared: + zammad-service: + &zammad-service # You can access the helpdesk at [zammad.app.localhost](https://zammad.app.localhost/). + deploy: + labels: + - dargstack.profiles=zammad + environment: &zammad-environment + ELASTICSEARCH_HOST: elasticsearch + ELASTICSEARCH_SCHEMA: https + ELASTICSEARCH_USER: elastic + MEMCACHE_SERVERS: memcached:11211 + NGINX_SERVER_SCHEME: https + POSTGRESQL_DB: zammad + POSTGRESQL_DB_CREATE: "false" + POSTGRESQL_HOST: postgres + POSTGRESQL_OPTIONS: ?pool=50 + REDIS_URL: redis://redis:6379 + image: ghcr.io/zammad/zammad:6.5.2-90 + secrets: + - source: elasticsearch-password + target: /run/environment-variables/ELASTICSEARCH_PASS + - source: postgres-role-service-zammad-username + target: /run/environment-variables/POSTGRESQL_USER + - source: postgres-role-service-zammad-password + target: /run/environment-variables/POSTGRESQL_PASS + volumes: + - zammad-data:/opt/zammad/storage + - ./configurations/docker-entrypoint.sh:/docker-entrypoint.sh:ro +services: + zammad-backup: + # You cannot access the helpdesk backup service via a web interface. + <<: *zammad-service + command: ["zammad-backup"] + user: 0:0 + volumes: + - zammad-backup-data:/var/tmp/zammad + - zammad-data:/opt/zammad/storage:ro + - ./configurations/docker-entrypoint.sh:/docker-entrypoint.sh:ro + zammad-init: + # You cannot access the helpdesk initialization service via a web interface. + <<: *zammad-service + command: ["zammad-init"] + deploy: + labels: + - dargstack.profiles=zammad + restart_policy: + condition: on-failure + user: 0:0 + zammad-nginx: + # You can access the helpdesk at [zammad.app.localhost](https://zammad.app.localhost/). + <<: *zammad-service + command: ["zammad-nginx"] + deploy: + labels: + - dargstack.profiles=zammad + - traefik.enable=true + - traefik.http.routers.zammad.entryPoints=web + - traefik.http.routers.zammad.middlewares=redirectscheme # dargstack:dev-only + - traefik.http.routers.zammad.rule=Host(`zammad.${STACK_DOMAIN}`) + - traefik.http.routers.zammad-secure.entryPoints=web-secure + - traefik.http.routers.zammad-secure.rule=Host(`zammad.${STACK_DOMAIN}`) + - traefik.http.routers.zammad-secure.tls.options=mintls13@file # dargstack:dev-only + - traefik.http.services.zammad.loadbalancer.server.port=8080 + zammad-railsserver: + # You cannot access the helpdesk application server directly. + <<: *zammad-service + command: ["zammad-railsserver"] + zammad-scheduler: + # You cannot access the helpdesk scheduler directly. + <<: *zammad-service + command: ["zammad-scheduler"] + zammad-websocket: + # You cannot access the helpdesk websocket server directly. + <<: *zammad-service + command: ["zammad-websocket"] +volumes: + zammad-backup-data: + # The helpdesk backup's data. + {} + zammad-data: + # The helpdesk's data. + {} diff --git a/src/production/configurations/zammad/docker-entrypoint.sh b/src/development/zammad/configurations/docker-entrypoint.sh similarity index 100% rename from src/production/configurations/zammad/docker-entrypoint.sh rename to src/development/zammad/configurations/docker-entrypoint.sh diff --git a/src/production/adminer/compose.yaml b/src/production/adminer/compose.yaml new file mode 100644 index 00000000..cbe52b06 --- /dev/null +++ b/src/production/adminer/compose.yaml @@ -0,0 +1,6 @@ +services: + adminer: + deploy: + labels: + - (( append )) + - traefik.http.routers.adminer-secure.tls.certresolver=default diff --git a/src/production/backups/postgres/README.md b/src/production/backups/postgres/README.md deleted file mode 100644 index a78acebf..00000000 --- a/src/production/backups/postgres/README.md +++ /dev/null @@ -1,3 +0,0 @@ - - -This directory contains backups created by [prodrigestivill/postgres-backup-local](https://github.com/prodrigestivill/docker-postgres-backup-local). diff --git a/src/production/cloudflared/compose.yaml b/src/production/cloudflared/compose.yaml new file mode 100644 index 00000000..9fddd7ed --- /dev/null +++ b/src/production/cloudflared/compose.yaml @@ -0,0 +1,10 @@ +services: + cloudflared: + # You can configure the secure tunnel at [dash.cloudflare.com](https://dash.cloudflare.com/). + command: tunnel run + deploy: + labels: + - dargstack.profiles=default + environment: + TUNNEL_TOKEN: ${CLOUDFLARED_TUNNEL_TOKEN} + image: cloudflare/cloudflared diff --git a/src/production/compose.yaml b/src/production/compose.yaml new file mode 100644 index 00000000..adefef00 --- /dev/null +++ b/src/production/compose.yaml @@ -0,0 +1,2 @@ +volumes: + pnpm-data: (( prune )) diff --git a/src/production/configurations/adminer/adminer.css b/src/production/configurations/adminer/adminer.css deleted file mode 100755 index c77609cb..00000000 --- a/src/production/configurations/adminer/adminer.css +++ /dev/null @@ -1,7 +0,0 @@ -a { - color: blue; -} - -a:visited { - color: blue; -} diff --git a/src/production/configurations/grafana/provisioning/datasources/postgres.yaml b/src/production/configurations/grafana/provisioning/datasources/postgres.yaml deleted file mode 100644 index f39d522b..00000000 --- a/src/production/configurations/grafana/provisioning/datasources/postgres.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: 1 - -datasources: - - access: proxy - jsonData: - database: $__file{/run/secrets/postgres_db} - postgresVersion: 1500 - sslmode: 'disable' - name: PostgreSQL - secureJsonData: - password: $__file{/run/secrets/postgres_role_service_grafana_password} - type: grafana-postgresql-datasource - url: postgres:5432 - user: $__file{/run/secrets/postgres_role_service_grafana_username} diff --git a/src/production/grafana/compose.yaml b/src/production/grafana/compose.yaml new file mode 100644 index 00000000..703cdaa0 --- /dev/null +++ b/src/production/grafana/compose.yaml @@ -0,0 +1,6 @@ +services: + grafana: + deploy: + labels: + - (( append )) + - traefik.http.routers.grafana-secure.tls.certresolver=default diff --git a/src/production/jobber/compose.yaml b/src/production/jobber/compose.yaml new file mode 100644 index 00000000..df5db9ff --- /dev/null +++ b/src/production/jobber/compose.yaml @@ -0,0 +1,7 @@ +services: + jobber: + environment: + SENTRY_CRONS: ${SENTRY_CRONS} + volumes: + - (( append )) + - postgres-backup-data:/backups/ diff --git a/src/production/configurations/jobber/.jobber b/src/production/jobber/configurations/.jobber similarity index 100% rename from src/production/configurations/jobber/.jobber rename to src/production/jobber/configurations/.jobber diff --git a/src/production/minio/compose.yaml b/src/production/minio/compose.yaml new file mode 100644 index 00000000..afb70a8c --- /dev/null +++ b/src/production/minio/compose.yaml @@ -0,0 +1,4 @@ +# services: +# minio: (( prune )) # breaks renovate +volumes: + minio_data: (( prune )) diff --git a/src/production/portainer/compose.yaml b/src/production/portainer/compose.yaml new file mode 100644 index 00000000..4d42fef0 --- /dev/null +++ b/src/production/portainer/compose.yaml @@ -0,0 +1,6 @@ +services: + portainer: + deploy: + labels: + - (( append )) + - traefik.http.routers.portainer-secure.tls.certresolver=default diff --git a/src/production/postgraphile/compose.yaml b/src/production/postgraphile/compose.yaml new file mode 100644 index 00000000..abc134da --- /dev/null +++ b/src/production/postgraphile/compose.yaml @@ -0,0 +1,8 @@ +services: + postgraphile: + deploy: + labels: + - (( append )) + - traefik.http.routers.postgraphile.middlewares=postgraphile-auth,postgraphile-cors + - traefik.http.routers.postgraphile-secure.tls.certresolver=default + image: maevsi/postgraphile:2.0.0-beta.1 diff --git a/src/production/configurations/postgraphile/jwtRS256.key.pub b/src/production/postgraphile/configurations/jwtRS256.key.pub similarity index 100% rename from src/production/configurations/postgraphile/jwtRS256.key.pub rename to src/production/postgraphile/configurations/jwtRS256.key.pub diff --git a/src/production/postgres/compose.yaml b/src/production/postgres/compose.yaml new file mode 100644 index 00000000..a85f6aad --- /dev/null +++ b/src/production/postgres/compose.yaml @@ -0,0 +1,24 @@ +secrets: + postgres-backup-db: + # The database's name. + external: true +services: + postgres-backup: + # You cannot access the database backup directly. + environment: + POSTGRES_DB_FILE: /run/secrets/postgres-backup-db + POSTGRES_HOST: postgres + POSTGRES_PASSWORD_FILE: /run/secrets/postgres-password + POSTGRES_USER_FILE: /run/secrets/postgres-user + image: prodrigestivill/postgres-backup-local:18-alpine + secrets: + - postgres-backup-db + - postgres-password + - postgres-user + volumes: + - postgres-data:/var/lib/postgresql/ + - postgres-backup-data:/backups/ +volumes: + postgres-backup-data: + # The database backup's data. + {} diff --git a/src/production/production.env.template b/src/production/production.env.template deleted file mode 100644 index 8ffc032b..00000000 --- a/src/production/production.env.template +++ /dev/null @@ -1,5 +0,0 @@ -CLOUDFLARED_TUNNEL_TOKEN= -SENTRY_CRONS= -STACK_DOMAIN= -TRAEFIK_ACME_EMAIL= -TRAEFIK_ACME_PROVIDER= \ No newline at end of file diff --git a/src/production/production.yml b/src/production/production.yml deleted file mode 100644 index beca404e..00000000 --- a/src/production/production.yml +++ /dev/null @@ -1,177 +0,0 @@ -secrets: - postgres-backup_db: - # The database's name. - external: true - traefik_cf-dns-api-token: - # The DNS provider's DNS API token. - external: true - traefik_cf-zone-api-token: - # The DNS provider's zone API token. - external: true -services: - adminer: - deploy: - labels: - - (( append )) - - traefik.http.routers.adminer_secure.tls.certresolver=default - cloudflared: - # You can configure the secure tunnel at [dash.cloudflare.com](https://dash.cloudflare.com/). - command: tunnel run - environment: - TUNNEL_TOKEN: ${CLOUDFLARED_TUNNEL_TOKEN} - image: cloudflare/cloudflared - grafana: - deploy: - labels: - - (( append )) - - traefik.http.routers.grafana_secure.tls.certresolver=default - jobber: - environment: - SENTRY_CRONS: ${SENTRY_CRONS} - volumes: - - (( append )) - - ./configurations/jobber/sinks:/srv/sinks:ro - # minio: (( prune )) # breaks renovate - portainer: - deploy: - labels: - - (( append )) - - traefik.http.routers.portainer_secure.tls.certresolver=default - postgraphile: - deploy: - labels: - - (( append )) - - traefik.http.routers.postgraphile.middlewares=postgraphile_auth,postgraphile_cors - - traefik.http.routers.postgraphile_secure.tls.certresolver=default - image: maevsi/postgraphile:2.0.0-beta.1 - postgres_backup: - # You cannot access the database backup directly. - environment: - POSTGRES_DB_FILE: /run/secrets/postgres-backup_db - POSTGRES_HOST: postgres - POSTGRES_PASSWORD_FILE: /run/secrets/postgres_password - POSTGRES_USER_FILE: /run/secrets/postgres_user - image: prodrigestivill/postgres-backup-local:18-alpine - secrets: - - postgres-backup_db - - postgres_password - - postgres_user - volumes: - - postgres_data:/var/lib/postgresql/ - - ../production/backups/postgres/:/backups/ - prometheus: - deploy: - labels: - - (( append )) - - traefik.http.routers.prometheus_secure.tls.certresolver=default - reccoom: - deploy: (( prune )) - image: ghcr.io/maevsi/reccoom:0.8.1 - redpanda-console: - deploy: - labels: - - (( append )) - - traefik.http.routers.redpanda_secure.tls.certresolver=default - sqitch: - image: ghcr.io/maevsi/sqitch:10.0.6 - volumes: (( prune )) - traefik: - command: - - (( prepend )) - - --certificatesResolvers.default.acme.email=${TRAEFIK_ACME_EMAIL} - - --certificatesResolvers.default.acme.storage=/etc/traefik/acme/acme.json - - --certificatesResolvers.default.acme.dnsChallenge.provider=${TRAEFIK_ACME_PROVIDER} - deploy: - labels: - - (( append )) - - traefik.http.routers.traefik_secure.tls.certresolver=default - environment: - CF_DNS_API_TOKEN_FILE: /run/secrets/traefik_cf-dns-api-token - CF_ZONE_API_TOKEN_FILE: /run/secrets/traefik_cf-zone-api-token - secrets: - - traefik_cf-dns-api-token - - traefik_cf-zone-api-token - traefik_certs-dumper: - # You cannot access the reverse proxy's certificate helper directly. - command: - - file - - --clean=false - - --crt-name="$STACK_DOMAIN" - - --dest=/etc/traefik/acme/ - - --key-name="$STACK_DOMAIN" - - --source=/etc/traefik/acme/acme.json - - --version=v2 - - --watch - environment: - STACK_DOMAIN: ${STACK_DOMAIN} - image: ldez/traefik-certs-dumper:v2.11.0 - volumes: - - acme_data:/etc/traefik/acme/ - tusd: - deploy: - labels: - - (( append )) - - traefik.http.routers.tusd.middlewares=tusd_cors - - traefik.http.routers.tusd_secure.tls.certresolver=default - vibetype: - deploy: - labels: - - (( append )) - - traefik.http.routers.vibetype.middlewares=vibetype_cors,vibetype_redirectregex - - traefik.http.routers.vibetype_secure.tls.certresolver=default - image: ghcr.io/maevsi/vibetype:13.3.3 - user: (( prune )) - # vibetype_beta: - # # You can access the main project frontend's beta version at [beta.app.localhost](https://beta.app.localhost/). - # deploy: - # labels: - # - traefik.enable=true - # - traefik.http.routers.vibetype_beta.entryPoints=web - # - traefik.http.routers.vibetype_beta.middlewares=vibetype_cors,vibetype_redirectregex - # - traefik.http.routers.vibetype_beta.rule=Host(`beta.${STACK_DOMAIN}`) - # - traefik.http.routers.vibetype_beta_secure.entryPoints=web-secure - # - traefik.http.routers.vibetype_beta_secure.middlewares=vibetype_cors,vibetype_redirectregex - # - traefik.http.routers.vibetype_beta_secure.rule=Host(`beta.${STACK_DOMAIN}`) - # - traefik.http.services.vibetype_beta.loadbalancer.server.port=3000 - # - traefik.http.routers.vibetype_beta_secure.tls.certresolver=default - # environment: - # AWS_REGION: ${VIBETYPE_AWS_REGION} - # NUXT_PUBLIC_GTAG_ID: ${VIBETYPE_NUXT_PUBLIC_GTAG_ID} - # NUXT_PUBLIC_I18N_BASE_URL: https://${STACK_DOMAIN} - # NUXT_PUBLIC_SITE_URL: https://${STACK_DOMAIN} - # NUXT_PUBLIC_TURNSTILE_SITE_KEY: ${VIBETYPE_NUXT_PUBLIC_TURNSTILE_SITE_KEY} - # NUXT_PUBLIC_VIBETYPE_EMAIL_LIMIT24H: ${VIBETYPE_NUXT_PUBLIC_VIBETYPE_EMAIL_LIMIT24H} - # NUXT_PUBLIC_VIO_ENVIRONMENT: beta - # PGHOST: postgres - # image: ghcr.io/maevsi/vibetype:11.0.2 - # secrets: - # - source: vibetype_api-notification-secret - # target: /run/environment-variables/NUXT_PRIVATE_API_NOTIFICATION_SECRET - # - source: vibetype_aws-credentials - # target: /home/node/.aws/credentials # TODO: switch to user `node` - # - source: vibetype_firebase-service-account-credentials - # target: /run/environment-variables/FIREBASE_SERVICE_ACCOUNT_CREDENTIALS - # - source: vibetype_openai-api-key - # target: /run/environment-variables/NUXT_PRIVATE_OPENAI_API_KEY - # - source: vibetype_turnstile-key - # target: /run/environment-variables/NUXT_TURNSTILE_SECRET_KEY - # - source: postgres_db - # target: /run/environment-variables/PGDATABASE - # - source: postgres_role_service_vibetype_password - # target: /run/environment-variables/PGPASSWORD - # - source: postgres_role_service_vibetype_username - # target: /run/environment-variables/PGUSER - # volumes: - # - ./configurations/postgraphile/jwtRS256.key.pub:/run/environment-variables/NUXT_PUBLIC_VIO_AUTH_JWT_PUBLIC_KEY:ro - zammad-nginx: - deploy: - labels: - - (( append )) - - traefik.http.routers.zammad_secure.tls.certresolver=default -version: "3.7" -volumes: - acme_data: - # The reverse proxy's certificate data. - {} - minio_data: (( prune )) - vibetype_data: (( prune )) diff --git a/src/production/prometheus/compose.yaml b/src/production/prometheus/compose.yaml new file mode 100644 index 00000000..f899c1f5 --- /dev/null +++ b/src/production/prometheus/compose.yaml @@ -0,0 +1,6 @@ +services: + prometheus: + deploy: + labels: + - (( append )) + - traefik.http.routers.prometheus-secure.tls.certresolver=default diff --git a/src/production/reccoom/compose.yaml b/src/production/reccoom/compose.yaml new file mode 100644 index 00000000..0690e333 --- /dev/null +++ b/src/production/reccoom/compose.yaml @@ -0,0 +1,4 @@ +services: + reccoom: + deploy: (( prune )) + image: ghcr.io/maevsi/reccoom:0.8.1 diff --git a/src/production/redpanda/compose.yaml b/src/production/redpanda/compose.yaml new file mode 100644 index 00000000..224787c6 --- /dev/null +++ b/src/production/redpanda/compose.yaml @@ -0,0 +1,6 @@ +services: + redpanda-console: + deploy: + labels: + - (( append )) + - traefik.http.routers.redpanda-secure.tls.certresolver=default diff --git a/src/production/sqitch/compose.yaml b/src/production/sqitch/compose.yaml new file mode 100644 index 00000000..e1a9dc91 --- /dev/null +++ b/src/production/sqitch/compose.yaml @@ -0,0 +1,4 @@ +services: + sqitch: + image: ghcr.io/maevsi/sqitch:10.0.6 + volumes: (( prune )) diff --git a/src/production/traefik/compose.yaml b/src/production/traefik/compose.yaml new file mode 100644 index 00000000..a7f41d9c --- /dev/null +++ b/src/production/traefik/compose.yaml @@ -0,0 +1,44 @@ +secrets: + traefik-cf-dns-api-token: + # The DNS provider's DNS API token. + external: true + traefik-cf-zone-api-token: + # The DNS provider's zone API token. + external: true +services: + traefik: + command: + - (( prepend )) + - --certificatesResolvers.default.acme.email=${TRAEFIK_ACME_EMAIL} + - --certificatesResolvers.default.acme.storage=/etc/traefik/acme/acme.json + - --certificatesResolvers.default.acme.dnsChallenge.provider=${TRAEFIK_ACME_PROVIDER} + deploy: + labels: + - (( append )) + - traefik.http.routers.traefik-secure.tls.certresolver=default + environment: + CF_DNS_API_TOKEN_FILE: /run/secrets/traefik-cf-dns-api-token + CF_ZONE_API_TOKEN_FILE: /run/secrets/traefik-cf-zone-api-token + secrets: + - traefik-cf-dns-api-token + - traefik-cf-zone-api-token + traefik-certs-dumper: + # You cannot access the reverse proxy's certificate helper directly. + command: + - file + - --clean=false + - --crt-name="$STACK_DOMAIN" + - --dest=/etc/traefik/acme/ + - --key-name="$STACK_DOMAIN" + - --source=/etc/traefik/acme/acme.json + - --version=v2 + - --watch + environment: + STACK_DOMAIN: ${STACK_DOMAIN} + image: ldez/traefik-certs-dumper:v2.11.0 + volumes: + - acme-data:/etc/traefik/acme/ +volumes: + acme-data: + # The reverse proxy's certificate data. + {} diff --git a/src/production/tusd/compose.yaml b/src/production/tusd/compose.yaml new file mode 100644 index 00000000..6e97d0cc --- /dev/null +++ b/src/production/tusd/compose.yaml @@ -0,0 +1,7 @@ +services: + tusd: + deploy: + labels: + - (( append )) + - traefik.http.routers.tusd.middlewares=tusd-cors + - traefik.http.routers.tusd-secure.tls.certresolver=default diff --git a/src/production/vibetype/compose.yaml b/src/production/vibetype/compose.yaml new file mode 100644 index 00000000..72d52cd1 --- /dev/null +++ b/src/production/vibetype/compose.yaml @@ -0,0 +1,53 @@ +services: + vibetype: + deploy: + labels: + - (( append )) + - traefik.http.routers.vibetype.middlewares=vibetype_cors,vibetype_redirectregex + - traefik.http.routers.vibetype-secure.tls.certresolver=default + image: ghcr.io/maevsi/vibetype:13.3.3 + user: (( prune )) + # vibetype-beta: + # # You can access the main project frontend's beta version at [beta.app.localhost](https://beta.app.localhost/). + # deploy: + # labels: + # - traefik.enable=true + # - traefik.http.routers.vibetype-beta.entryPoints=web + # - traefik.http.routers.vibetype-beta.middlewares=vibetype_cors,vibetype_redirectregex + # - traefik.http.routers.vibetype-beta.rule=Host(`beta.${STACK_DOMAIN}`) + # - traefik.http.routers.vibetype-beta-secure.entryPoints=web-secure + # - traefik.http.routers.vibetype-beta-secure.middlewares=vibetype_cors,vibetype_redirectregex + # - traefik.http.routers.vibetype-beta-secure.rule=Host(`beta.${STACK_DOMAIN}`) + # - traefik.http.services.vibetype-beta.loadbalancer.server.port=3000 + # - traefik.http.routers.vibetype-beta-secure.tls.certresolver=default + # environment: + # AWS_REGION: ${VIBETYPE_AWS_REGION} + # NUXT_PUBLIC_GTAG_ID: ${VIBETYPE_NUXT_PUBLIC_GTAG_ID} + # NUXT_PUBLIC_I18N_BASE_URL: https://${STACK_DOMAIN} + # NUXT_PUBLIC_SITE_URL: https://${STACK_DOMAIN} + # NUXT_PUBLIC_TURNSTILE_SITE_KEY: ${VIBETYPE_NUXT_PUBLIC_TURNSTILE_SITE_KEY} + # NUXT_PUBLIC_VIBETYPE_EMAIL_LIMIT24H: ${VIBETYPE_NUXT_PUBLIC_VIBETYPE_EMAIL_LIMIT24H} + # NUXT_PUBLIC_VIO_ENVIRONMENT: beta + # PGHOST: postgres + # image: ghcr.io/maevsi/vibetype:11.0.2 + # secrets: + # - source: vibetype-api-notification-secret + # target: /run/environment-variables/NUXT_PRIVATE_API_NOTIFICATION_SECRET + # - source: vibetype-aws-credentials + # target: /home/node/.aws/credentials # TODO: switch to user `node` + # - source: vibetype-firebase-service-account-credentials + # target: /run/environment-variables/FIREBASE_SERVICE_ACCOUNT_CREDENTIALS + # - source: vibetype-openai-api-key + # target: /run/environment-variables/NUXT_PRIVATE_OPENAI_API_KEY + # - source: vibetype-turnstile-key + # target: /run/environment-variables/NUXT_TURNSTILE_SECRET_KEY + # - source: postgres-db + # target: /run/environment-variables/PGDATABASE + # - source: postgres-role-service-vibetype-password + # target: /run/environment-variables/PGPASSWORD + # - source: postgres-role-service-vibetype-username + # target: /run/environment-variables/PGUSER + # volumes: + # - ./configurations/postgraphile/jwtRS256.key.pub:/run/environment-variables/NUXT_PUBLIC_VIO_AUTH_JWT_PUBLIC_KEY:ro +volumes: + vibetype_data: (( prune )) diff --git a/src/production/zammad/compose.yaml b/src/production/zammad/compose.yaml new file mode 100644 index 00000000..60f892ef --- /dev/null +++ b/src/production/zammad/compose.yaml @@ -0,0 +1,6 @@ +services: + zammad-nginx: + deploy: + labels: + - (( append )) + - traefik.http.routers.zammad-secure.tls.certresolver=default