From 7caf70941381ffe6320875c7c9d147eb08254a37 Mon Sep 17 00:00:00 2001 From: Jere Salonen Date: Tue, 23 Apr 2024 19:59:16 +0200 Subject: [PATCH 001/863] feat: Add EdgeDB edgedb.svg includes EdgeDB logo and add edgedb.yaml the configuration for edgedb and postgres services. Commit includes setting environment variables, volumes, health checks, and ports. --- public/svgs/edgedb.svg | 3 +++ templates/compose/edgedb.yaml | 43 +++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 public/svgs/edgedb.svg create mode 100644 templates/compose/edgedb.yaml diff --git a/public/svgs/edgedb.svg b/public/svgs/edgedb.svg new file mode 100644 index 000000000..a906f7f7e --- /dev/null +++ b/public/svgs/edgedb.svg @@ -0,0 +1,3 @@ + + + diff --git a/templates/compose/edgedb.yaml b/templates/compose/edgedb.yaml new file mode 100644 index 000000000..62c6e8000 --- /dev/null +++ b/templates/compose/edgedb.yaml @@ -0,0 +1,43 @@ +# documentation: https://www.edgedb.com +# slogan: An open-source database designed as a spiritual successor to SQL and the relational paradigm. Powered by the Postgres query engine under the hood. +# tags: db database sql +# logo: svgs/edgedb.svg + +services: + edgedb: + image: edgedb/edgedb + environment: + - EDGEDB_SERVER_ADMIN_UI=${EDGEDB_SERVER_ADMIN_UI:-enabled} + - EDGEDB_SERVER_BACKEND_DSN=postgres://$SERVICE_USER_POSTGRES:$SERVICE_PASSWORD_POSTGRES@postgresql:5432/$POSTGRES_DB + - EDGEDB_SERVER_SECURITY=strict + - EDGEDB_SERVER_PASSWORD=$SERVICE_EDGEDB_SERVER_PASSWORD + - EDGEDB_SERVER_TLS_CERT_MODE=generate_self_signed + # - EDGEDB_SERVER_TLS_CERT_FILE= # Ideally Coolify should generate its own certificates + # - EDGEDB_SERVER_TLS_KEY_FILE= # -- || -- + - POSTGRES_DB=${POSTGRES_DB:-edgedb} + + depends_on: + postgresql: + condition: service_healthy + volumes: + - "./dbschema:/dbschema" + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:5656/server/status/alive"] + interval: 5s + timeout: 20s + retries: 10 + ports: + - "5656:5656" + postgresql: + image: postgres:16-alpine + volumes: + - postgresql-data:/var/lib/postgresql/data + environment: + - POSTGRES_USER=$SERVICE_USER_POSTGRES + - POSTGRES_PASSWORD=$SERVICE_PASSWORD_POSTGRES + - POSTGRES_DB=${POSTGRES_DB:-edgedb} + healthcheck: + test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"] + interval: 5s + timeout: 20s + retries: 10 \ No newline at end of file From 03d347f082b86a4b8c980186884bc83b415d5c7e Mon Sep 17 00:00:00 2001 From: Jere Salonen Date: Tue, 23 Apr 2024 20:08:08 +0200 Subject: [PATCH 002/863] fix: Add port metadata and Coolify magic to generate the domain --- templates/compose/edgedb.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/templates/compose/edgedb.yaml b/templates/compose/edgedb.yaml index 62c6e8000..a4e127fa5 100644 --- a/templates/compose/edgedb.yaml +++ b/templates/compose/edgedb.yaml @@ -2,11 +2,13 @@ # slogan: An open-source database designed as a spiritual successor to SQL and the relational paradigm. Powered by the Postgres query engine under the hood. # tags: db database sql # logo: svgs/edgedb.svg +# port: 5656 services: edgedb: image: edgedb/edgedb environment: + - SERVICE_FQDN_EDGEDB - EDGEDB_SERVER_ADMIN_UI=${EDGEDB_SERVER_ADMIN_UI:-enabled} - EDGEDB_SERVER_BACKEND_DSN=postgres://$SERVICE_USER_POSTGRES:$SERVICE_PASSWORD_POSTGRES@postgresql:5432/$POSTGRES_DB - EDGEDB_SERVER_SECURITY=strict From 21fc8efb865f3d464d5d12dfc355f450fdfa4136 Mon Sep 17 00:00:00 2001 From: Alejandro Akbal <37181533+AlejandroAkbal@users.noreply.github.com> Date: Tue, 4 Jun 2024 13:13:37 +0100 Subject: [PATCH 003/863] feat: add Mixpost template --- public/svgs/mixpost.svg | 5 ++++ templates/compose/mixpost.yaml | 54 ++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 public/svgs/mixpost.svg create mode 100644 templates/compose/mixpost.yaml diff --git a/public/svgs/mixpost.svg b/public/svgs/mixpost.svg new file mode 100644 index 000000000..bd915e77a --- /dev/null +++ b/public/svgs/mixpost.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/templates/compose/mixpost.yaml b/templates/compose/mixpost.yaml new file mode 100644 index 000000000..7dffd55c6 --- /dev/null +++ b/templates/compose/mixpost.yaml @@ -0,0 +1,54 @@ +# documentation: https://docs.mixpost.app/lite +# slogan: Mixpost is a robust and versatile social media management software, designed to streamline social media operations and enhance content marketing strategies. +# tags: social media, marketing, content, management, automation, self-hosted +# logo: svgs/mixpost.svg +# port: 80 + +services: + mixpost: + image: 'inovector/mixpost:latest' + environment: + - SERVICE_FQDN_MIXPOST + - APP_NAME=Mixpost + - 'APP_KEY=${SERVICE_BASE64_MIXPOST}' + - APP_DEBUG=false + - 'APP_URL=${SERVICE_FQDN_MIXPOST}' + - 'DB_DATABASE=${MYSQL_DATABASE:-mixpost_db}' + - 'DB_USERNAME=${SERVICE_USERNAME_MYSQL}' + - 'DB_PASSWORD=${SERVICE_PASSWORD_MYSQL}' + volumes: + - 'mixpost-storage:/var/www/html/storage/app' + - 'mixpost-logs:/var/www/html/storage/logs' + depends_on: + - mysql + - redis + mysql: + image: 'mysql/mysql-server:8.0' + environment: + - 'MYSQL_DATABASE=${MYSQL_DATABASE:-mixpost_db}' + - 'MYSQL_USER=${SERVICE_USERNAME_MYSQL}' + - 'MYSQL_PASSWORD=${SERVICE_PASSWORD_MYSQL}' + - 'MYSQL_ROOT_PASSWORD=${SERVICE_PASSWORD_MYSQLROOT}' + volumes: + - 'mixpost-mysql:/var/lib/mysql' + healthcheck: + test: + - CMD + - mysqladmin + - ping + - '-h' + - 127.0.0.1 + - '-uroot' + - '-p${SERVICE_PASSWORD_MYSQLROOT}' + interval: 5s + timeout: 20s + retries: 10 + redis: + image: 'redis:alpine' + healthcheck: + test: + - CMD + - redis-cli + - '--raw' + - incr + - ping From 52626765962fa5bbfc44a36b2b2bb287553bb400 Mon Sep 17 00:00:00 2001 From: marcomaiermm Date: Sat, 8 Jun 2024 10:45:34 +0200 Subject: [PATCH 004/863] feat: Add Supertokens template --- public/svgs/supertokens.svg | 17 +++++++++++++++ templates/compose/supertokens.yaml | 35 ++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 public/svgs/supertokens.svg create mode 100644 templates/compose/supertokens.yaml diff --git a/public/svgs/supertokens.svg b/public/svgs/supertokens.svg new file mode 100644 index 000000000..30b435bd0 --- /dev/null +++ b/public/svgs/supertokens.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/templates/compose/supertokens.yaml b/templates/compose/supertokens.yaml new file mode 100644 index 000000000..703cab780 --- /dev/null +++ b/templates/compose/supertokens.yaml @@ -0,0 +1,35 @@ +# documentation: https://supertokens.com/docs/guides +# logo: svgs/supertokens.svg +# slogan: An open-source authentication solution that simplifies the implementation of secure user authentication and session management for web and mobile applications. +# tags: supertokens,login,authentication,authorization,oauth,user-management,session-management,access-control,otp,magic-link,passwordless +# port: 3567 + +services: + supertokens: + image: registry.supertokens.io/supertokens/supertokens-postgresql + depends_on: + db: + condition: service_healthy + environment: + - SERVICE_FQDN_SUPERTOKENS_3567 + - POSTGRESQL_CONNECTION_URI="postgresql://$SERVICE_USER_POSTGRESQL:$SERVICE_PASSWORD_POSTGRESQL@db:5432/${POSTGRES_DB:-supertokens}" + restart: unless-stopped + healthcheck: + test: "bash -c 'exec 3<>/dev/tcp/127.0.0.1/3567 && echo -e \"GET /hello HTTP/1.1\\r\\nhost: 127.0.0.1:3567\\r\\nConnection: close\\r\\n\\r\\n\" >&3 && cat <&3 | grep \"Hello\"'\n" + interval: 10s + timeout: 5s + retries: 5 + db: + image: postgres:16 + environment: + - POSTGRES_USER=$SERVICE_USER_POSTGRESQL + - POSTGRES_PASSWORD=$SERVICE_PASSWORD_POSTGRESQL + - POSTGRES_DB=${POSTGRES_DB:-supertokens} + volumes: + - supertokens-postgres-data:/var/lib/postgresql/data + restart: unless-stopped + healthcheck: + test: ["CMD", "pg_isready", "-U", "$SERVICE_USER_POSTGRESQL", "-d", "${POSTGRES_DB:-supertokens}"] + interval: 5s + timeout: 5s + retries: 5 From 7d1f760c532c769c4bb525c97d299adb2bb2d14d Mon Sep 17 00:00:00 2001 From: marcomaiermm Date: Sat, 8 Jun 2024 11:23:11 +0200 Subject: [PATCH 005/863] add optional api key --- templates/compose/supertokens.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/templates/compose/supertokens.yaml b/templates/compose/supertokens.yaml index 703cab780..f6ab90c5f 100644 --- a/templates/compose/supertokens.yaml +++ b/templates/compose/supertokens.yaml @@ -12,6 +12,7 @@ services: condition: service_healthy environment: - SERVICE_FQDN_SUPERTOKENS_3567 + - API_KEYS=${API_KEYS:-} - POSTGRESQL_CONNECTION_URI="postgresql://$SERVICE_USER_POSTGRESQL:$SERVICE_PASSWORD_POSTGRESQL@db:5432/${POSTGRES_DB:-supertokens}" restart: unless-stopped healthcheck: From 2637afcfb2f08f8d54678d3614318fc1fdc57083 Mon Sep 17 00:00:00 2001 From: Anthony Ly Date: Wed, 26 Jun 2024 09:51:12 +0200 Subject: [PATCH 006/863] add service template for azimutt --- public/svgs/azimutt.svg | 6 +++ templates/compose/azimutt.yaml | 76 ++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 public/svgs/azimutt.svg create mode 100644 templates/compose/azimutt.yaml diff --git a/public/svgs/azimutt.svg b/public/svgs/azimutt.svg new file mode 100644 index 000000000..223805fea --- /dev/null +++ b/public/svgs/azimutt.svg @@ -0,0 +1,6 @@ + + + + diff --git a/templates/compose/azimutt.yaml b/templates/compose/azimutt.yaml new file mode 100644 index 000000000..522c5a935 --- /dev/null +++ b/templates/compose/azimutt.yaml @@ -0,0 +1,76 @@ +# documentation: https://docs.azimutt.app/ +# slogan: Next-Gen ERD: Design, Explore, Document and Analyze your database. +# tags: erd, entity-relationship diagram, database tool, database schema, diagram +# icon: svgs/azimutt.svg +# port: 4000 + +services: + database: + image: postgres + restart: always + container_name: azimutt-db + environment: + - POSTGRES_PASSWORD=$SERVICE_PASSWORD_POSTGRESQL + - POSTGRES_USER=$SERVICE_USER_POSTGRESQL + - POSTGRES_DB=azimutt_app + volumes: + - pg-data:/var/lib/postgresql/data + storage: + image: quay.io/minio/minio:latest + command: server /data --console-address ":9001" + environment: + - MINIO_SERVER_URL=$MINIO_SERVER_URL + - MINIO_BROWSER_REDIRECT_URL=$MINIO_BROWSER_REDIRECT_URL + - MINIO_ROOT_USER=$SERVICE_USER_MINIO + - MINIO_ROOT_PASSWORD=$SERVICE_PASSWORD_MINIO + volumes: + - minio-data:/data + createbuckets: + image: minio/mc + depends_on: + - storage + entrypoint: > + /bin/sh -c " + /usr/bin/mc config host add myminio http://storage:9000 $SERVICE_USER_MINIO $SERVICE_PASSWORD_MINIO; + /usr/bin/mc mb -p myminio/azimutt; + /usr/bin/mc policy download myminio/azimutt; + exit 0; + " + smtp: + image: bytemark/smtp + environment: + - RELAY_HOST=$SERVICE_URL_SMTP + - RELAY_PORT=587 + - RELAY_USERNAME=$SERVICE_EMAIL_SMTP + - RELAY_PASSWORD=$SERVICE_PASSWORD_SMTP + backend: + container_name: azimutt-backend + platform: linux/amd64 + restart: always + image: ghcr.io/azimuttapp/azimutt:main + depends_on: + - database + - storage + ports: + - 4000:4000 + environment: + - SERVICE_FQDN_AZIMUTT + - PHX_SERVER=true + - PHX_HOST=$SERVICE_FQDN_AZIMUTT + - PORT=4000 + - DATABASE_URL=ecto://$SERVICE_USER_POSTGRESQL:$SERVICE_PASSWORD_POSTGRESQL@database/azimutt_app + - SECRET_KEY_BASE=$SERVICE_PASSWORD_64_AZIMUTT + - FILE_STORAGE_ADAPTER=s3 + - S3_BUCKET=azimutt + - S3_HOST=$MINIO_SERVER_URL + - S3_KEY_ID=$SERVICE_USER_MINIO + - S3_KEY_SECRET=$SERVICE_PASSWORD_MINIO + - AUTH_PASSWORD=true + - SKIP_ONBOARDING_FUNNEL=true + - SKIP_EMAIL_CONFIRMATION=true + - PUBLIC_SITE=false + - EMAIL_ADAPTER=smtp + - SMTP_RELAY=$SERVICE_URL_SMTP + - SMTP_USERNAME=$SERVICE_EMAIL_SMTP + - SMTP_PASSWORD=$SERVICE_PASSWORD_SMTP + - SMTP_PORT=587 \ No newline at end of file From ac887eefd67e6ca09d7ea7660ff0c982bf060d67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20Sz=C3=BCcs?= <2458236+martonsz@users.noreply.github.com> Date: Sat, 29 Jun 2024 18:52:06 +0200 Subject: [PATCH 007/863] Adding service for paperless fulfills: https://github.com/coollabsio/coolify/discussions/2349 This service is using a workaround for the issue mentioned here: https://github.com/coollabsio/coolify/discussions/2572 --- public/svgs/paperless.svg | 12 +++++++ templates/compose/paperless.yaml | 60 ++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 public/svgs/paperless.svg create mode 100644 templates/compose/paperless.yaml diff --git a/public/svgs/paperless.svg b/public/svgs/paperless.svg new file mode 100644 index 000000000..347b1e759 --- /dev/null +++ b/public/svgs/paperless.svg @@ -0,0 +1,12 @@ + + + + + + diff --git a/templates/compose/paperless.yaml b/templates/compose/paperless.yaml new file mode 100644 index 000000000..cb5f1ca76 --- /dev/null +++ b/templates/compose/paperless.yaml @@ -0,0 +1,60 @@ +# documentation: https://docs.paperless-ngx.com/configuration/ +# slogan: Paperless-ngx is a community-supported open-source document management system that transforms your physical documents into a searchable online archive so you can keep, well, less paper. +# logo: svgs/paperless.svg +# port: 8000 +services: + redis: + image: docker.io/library/redis:${REDIS_TAG:-7.2.5} + restart: unless-stopped + volumes: + - redis:/data + healthcheck: + test: ["CMD", "redis-cli", "ping"] + timeout: 10s + retries: 3 + + paperless: + image: paperlessngx/paperless-ngx:${PAPERLESS_TAG:-2.10.2} + restart: unless-stopped + depends_on: + redis: + condition: service_healthy + healthcheck: + test: ["CMD", "curl", "-fs", "-S", "--max-time", "2", "http://localhost:8000"] + interval: 30s + timeout: 10s + retries: 5 + volumes: + - data:/usr/src/paperless/data + - media:/usr/src/paperless/media + - type: bind + source: ./export + target: /usr/src/paperless/export + is_directory: true + - type: bind + source: ./consume + target: /usr/src/paperless/consume + is_directory: true + - type: bind + source: ./init-workaround.sh + target: /init-workaround.sh + content: | + #!/bin/bash + # Workaround for https://github.com/coollabsio/coolify/discussions/2572 + # Paperless won't start if the PAPERLESS_URL ends with a path. + if [[ "$PAPERLESS_URL" == */ ]]; then + PAPERLESS_URL="${PAPERLESS_URL%/}" + export PAPERLESS_URL + fi + # Run the original entrypoint + # ENTRYPOINT CMD + exec /sbin/docker-entrypoint.sh /usr/local/bin/paperless_cmd.sh + entrypoint: ["/init-workaround.sh"] + environment: + - PAPERLESS_ADMIN_PASSWORD=$SERVICE_PASSWORD_PAPERLESS_ADMIN + - PAPERLESS_ADMIN_USER=${PAPERLESS_ADMIN_USER:-admin} + - PAPERLESS_REDIS=redis://redis:6379 + - PAPERLESS_SECRET_KEY=$SERVICE_PASSWORD_64_PAPERLESSSECRETKEY + - PAPERLESS_URL=${PAPERLESS_URL:-$SERVICE_FQDN_PAPERLESS} + - SERVICE_FQDN_PAPERLESS + \ No newline at end of file From 384707639213af3381dec03e59590072dc2e3384 Mon Sep 17 00:00:00 2001 From: Italo Date: Sat, 29 Jun 2024 18:04:15 -0400 Subject: [PATCH 008/863] feat: adds forgejo service with runners --- templates/compose/forgejo-with-mariadb.yaml | 45 ++++++ templates/compose/forgejo-with-mysql.yaml | 46 +++++++ .../compose/forgejo-with-postgresql.yaml | 44 ++++++ .../compose/forgejo-with-runner-mariadb.yaml | 128 ++++++++++++++++++ .../forgejo-with-runner-with-mysql.yaml | 128 ++++++++++++++++++ .../forgejo-with-runner-with-postgresql.yaml | 127 +++++++++++++++++ templates/compose/forgejo-with-runner.yaml | 105 ++++++++++++++ templates/compose/forgejo.yaml | 22 +++ 8 files changed, 645 insertions(+) create mode 100644 templates/compose/forgejo-with-mariadb.yaml create mode 100644 templates/compose/forgejo-with-mysql.yaml create mode 100644 templates/compose/forgejo-with-postgresql.yaml create mode 100644 templates/compose/forgejo-with-runner-mariadb.yaml create mode 100644 templates/compose/forgejo-with-runner-with-mysql.yaml create mode 100644 templates/compose/forgejo-with-runner-with-postgresql.yaml create mode 100644 templates/compose/forgejo-with-runner.yaml create mode 100644 templates/compose/forgejo.yaml diff --git a/templates/compose/forgejo-with-mariadb.yaml b/templates/compose/forgejo-with-mariadb.yaml new file mode 100644 index 000000000..e1d49515b --- /dev/null +++ b/templates/compose/forgejo-with-mariadb.yaml @@ -0,0 +1,45 @@ +# documentation: https://forgejo.org/docs +# slogan: Forgejo is a self-hosted lightweight software forge. Easy to install and low maintenance, it just does the job. +# tags: version control, collaboration, code, hosting, lightweight, mariadb +# logo: svgs/forgejo.svg + +services: + forgejo: + image: codeberg.org/forgejo/forgejo:7 + environment: + - USER_UID=1000 + - USER_GID=1000 + - DB_TYPE=mysql + - HOST=mariadb + - NAME=${MYSQL_DATABASE-forgejo} + - USER=$SERVICE_USER_MYSQL + - PASSWD=$SERVICE_PASSWORD_MYSQL + volumes: + - forgejo-data:/data + - forgejo-timezone:/etc/timezone:ro + - forgejo-localtime:/etc/localtime:ro + ports: + - 22222:22 + depends_on: + mariadb: + condition: service_healthy + healthcheck: + test: ["CMD", "curl", "-f", "http://127.0.0.1:3000"] + interval: 2s + timeout: 10s + retries: 15 + + mariadb: + image: mariadb:11 + volumes: + - forgejo-mariadb-data:/var/lib/mysql + environment: + - MYSQL_USER=${SERVICE_USER_MYSQL} + - MYSQL_PASSWORD=${SERVICE_PASSWORD_MYSQL} + - MYSQL_DATABASE=${MYSQL_DATABASE} + - MYSQL_ROOT_PASSWORD=${SERVICE_PASSWORD_MYSQLROOT} + healthcheck: + test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"] + interval: 5s + timeout: 20s + retries: 10 diff --git a/templates/compose/forgejo-with-mysql.yaml b/templates/compose/forgejo-with-mysql.yaml new file mode 100644 index 000000000..f46b2c447 --- /dev/null +++ b/templates/compose/forgejo-with-mysql.yaml @@ -0,0 +1,46 @@ +# documentation: https://forgejo.org/docs +# slogan: Forgejo is a self-hosted lightweight software forge. Easy to install and low maintenance, it just does the job. +# tags: version control, collaboration, code, hosting, lightweight, mysql +# logo: svgs/forgejo.svg + +services: + forgejo: + image: codeberg.org/forgejo/forgejo:7 + environment: + - SERVICE_FQDN_FORGEJO_3000 + - USER_UID=1000 + - USER_GID=1000 + - DB_TYPE=mysql + - HOST=mysql + - NAME=${MYSQL_DATABASE-forgejo} + - USER=$SERVICE_USER_MYSQL + - PASSWD=$SERVICE_PASSWORD_MYSQL + volumes: + - forgejo-data:/data + - forgejo-timezone:/etc/timezone:ro + - forgejo-localtime:/etc/localtime:ro + ports: + - 22222:22 + depends_on: + mysql: + condition: service_healthy + healthcheck: + test: ["CMD", "curl", "-f", "http://127.0.0.1:3000"] + interval: 2s + timeout: 10s + retries: 15 + + mysql: + image: mysql:8 + volumes: + - forgejo-mysql-data:/var/lib/mysql + environment: + - MYSQL_USER=${SERVICE_USER_MYSQL} + - MYSQL_PASSWORD=${SERVICE_PASSWORD_MYSQL} + - MYSQL_DATABASE=${MYSQL_DATABASE} + - MYSQL_ROOT_PASSWORD=${SERVICE_PASSWORD_MYSQLROOT} + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1"] + interval: 5s + timeout: 20s + retries: 10 diff --git a/templates/compose/forgejo-with-postgresql.yaml b/templates/compose/forgejo-with-postgresql.yaml new file mode 100644 index 000000000..4c39fc1b9 --- /dev/null +++ b/templates/compose/forgejo-with-postgresql.yaml @@ -0,0 +1,44 @@ +# documentation: https://forgejo.org/docs +# slogan: Forgejo is a self-hosted lightweight software forge. Easy to install and low maintenance, it just does the job. +# tags: version control, collaboration, code, hosting, lightweight, postgresql +# logo: svgs/forgejo.svg + +services: + forgejo: + image: codeberg.org/forgejo/forgejo:7 + environment: + - USER_UID=1000 + - USER_GID=1000 + - DB_TYPE=postgres + - HOST=postgresql + - NAME=${POSTGRESQL_DATABASE-forgejo} + - USER=$SERVICE_USER_POSTGRESQL + - PASSWD=$SERVICE_PASSWORD_POSTGRESQL + volumes: + - forgejo-data:/data + - forgejo-timezone:/etc/timezone:ro + - forgejo-localtime:/etc/localtime:ro + ports: + - 22222:22 + depends_on: + postgresql: + condition: service_healthy + healthcheck: + test: ["CMD", "curl", "-f", "http://127.0.0.1:3000"] + interval: 2s + timeout: 10s + retries: 15 + + postgresql: + image: postgres:16-alpine + volumes: + - forgejo-postgresql-data:/var/lib/postgresql/data + environment: + - POSTGRES_USER=${SERVICE_USER_POSTGRESQL} + - POSTGRES_PASSWORD=${SERVICE_PASSWORD_POSTGRESQL} + - POSTGRES_DB=${POSTGRESQL_DATABASE} + healthcheck: + test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"] + interval: 5s + timeout: 20s + retries: 10 diff --git a/templates/compose/forgejo-with-runner-mariadb.yaml b/templates/compose/forgejo-with-runner-mariadb.yaml new file mode 100644 index 000000000..1f4b932d1 --- /dev/null +++ b/templates/compose/forgejo-with-runner-mariadb.yaml @@ -0,0 +1,128 @@ +# documentation: https://forgejo.org/docs +# slogan: Forgejo is a self-hosted lightweight software forge. Easy to install and low maintenance, it just does the job. +# tags: version control, collaboration, code, hosting, lightweight, runner, actions +# logo: svgs/forgejo.svg + +services: + forgejo: + image: codeberg.org/forgejo/forgejo:7 + environment: + - SERVICE_FQDN_FORGEJO_3000 + - RUNNER_SHARED_SECRET=${RUNNER_SHARED_SECRET} + - USER_UID=1000 + - USER_GID=1000 + - DB_TYPE=mysql + - HOST=mariadb + - NAME=${MYSQL_DATABASE-forgejo} + - USER=$SERVICE_USER_MYSQL + - PASSWD=$SERVICE_PASSWORD_MYSQL + - FORGEJO__repository__ENABLE_PUSH_CREATE_USER=true + - FORGEJO__repository__DEFAULT_PUSH_CREATE_PRIVATE=false + - FORGEJO__repository__DEFAULT_REPO_UNITS=repo.code,repo.actions + volumes: + - forgejo-data:/data + - forgejo-timezone:/etc/timezone:ro + - forgejo-localtime:/etc/localtime:ro + ports: + - 22222:22 + depends_on: + mariadb: + condition: service_healthy + healthcheck: + test: ["CMD", "curl", "-f", "http://127.0.0.1:3000"] + interval: 2s + timeout: 10s + retries: 15 + command: >- + bash -c ' + /bin/s6-svscan /etc/s6 & + sleep 10 ; + su -c "forgejo forgejo-cli actions register --secret ${RUNNER_SHARED_SECRET}" git ; + sleep infinity + ' + + mariadb: + image: mariadb:11 + volumes: + - forgejo-mariadb-data:/var/lib/mysql + environment: + - MYSQL_USER=${SERVICE_USER_MYSQL} + - MYSQL_PASSWORD=${SERVICE_PASSWORD_MYSQL} + - MYSQL_DATABASE=${MYSQL_DATABASE} + - MYSQL_ROOT_PASSWORD=${SERVICE_PASSWORD_MYSQLROOT} + healthcheck: + test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"] + interval: 5s + timeout: 20s + retries: 10 + + docker-in-docker: + image: docker:dind + hostname: docker + privileged: true + restart: 'unless-stopped' + healthcheck: + disable: true + environment: + DOCKER_TLS_CERTDIR: /certs + DOCKER_HOST: docker-in-docker + volumes: + - forgejo-did-certs:/certs + + runner-register: + image: code.forgejo.org/forgejo/runner:3.5.0 + restart: 'no' + links: + - docker-in-docker + - forgejo + environment: + - DOCKER_HOST=tcp://docker-in-docker:2376 + - RUNNER_SHARED_SECRET=${RUNNER_SHARED_SECRET} + volumes: + - forgejo-runner-data:/data + - forgejo-timezone:/etc/timezone:ro + - forgejo-localtime:/etc/localtime:ro + healthcheck: + disable: true + user: 0:0 + command: >- + bash -ec ' + while : ; do + forgejo-runner create-runner-file --connect --instance http://forgejo:3000 --name runner --secret ${RUNNER_SHARED_SECRET} && break ; + sleep 1 ; + done ; + sed -i -e "s|\"labels\": null|\"labels\": [\"docker:docker://node:20-bookworm\", \"ubuntu-22.04:docker://catthehacker/ubuntu:act-22.04\"]|" .runner ; + forgejo-runner generate-config > config.yml ; + sed -i -e "s|network: .*|network: host|" config.yml ; + sed -i -e "s|^ envs:$$| envs:\n DOCKER_HOST: tcp://docker:2376\n DOCKER_TLS_VERIFY: 1\n DOCKER_CERT_PATH: /certs/client|" config.yml ; + sed -i -e "s|^ options:| options: -v /certs/client:/certs/client|" config.yml ; + sed -i -e "s| valid_volumes: \[\]$$| valid_volumes:\n - /certs/client|" config.yml ; + chown -R 1000:1000 /data ; + exit 0 + ' + + runner: + image: code.forgejo.org/forgejo/runner:3.5.0 + links: + - docker-in-docker + - forgejo + depends_on: + docker-in-docker: + condition: service_started + environment: + - DOCKER_HOST=tcp://docker:2376 + - DOCKER_CERT_PATH=/certs/client + - DOCKER_TLS_VERIFY=1 + user: 1000:1000 + volumes: + - forgejo-runner-data:/data + - forgejo-did-certs:/certs + - forgejo-timezone:/etc/timezone:ro + - forgejo-localtime:/etc/localtime:ro + restart: 'unless-stopped' + healthcheck: + disable: true + command: >- + bash -c ' + while : ; do test -w .runner && forgejo-runner --config config.yml daemon ; sleep 1 ; done + ' \ No newline at end of file diff --git a/templates/compose/forgejo-with-runner-with-mysql.yaml b/templates/compose/forgejo-with-runner-with-mysql.yaml new file mode 100644 index 000000000..0dd87767e --- /dev/null +++ b/templates/compose/forgejo-with-runner-with-mysql.yaml @@ -0,0 +1,128 @@ +# documentation: https://forgejo.org/docs +# slogan: Forgejo is a self-hosted lightweight software forge. Easy to install and low maintenance, it just does the job. +# tags: version control, collaboration, code, hosting, lightweight, runner, actions +# logo: svgs/forgejo.svg + +services: + forgejo: + image: codeberg.org/forgejo/forgejo:7 + environment: + - SERVICE_FQDN_FORGEJO_3000 + - RUNNER_SHARED_SECRET=${RUNNER_SHARED_SECRET} + - USER_UID=1000 + - USER_GID=1000 + - DB_TYPE=mysql + - HOST=mysql + - NAME=${MYSQL_DATABASE-forgejo} + - USER=$SERVICE_USER_MYSQL + - PASSWD=$SERVICE_PASSWORD_MYSQL + - FORGEJO__repository__ENABLE_PUSH_CREATE_USER=true + - FORGEJO__repository__DEFAULT_PUSH_CREATE_PRIVATE=false + - FORGEJO__repository__DEFAULT_REPO_UNITS=repo.code,repo.actions + volumes: + - forgejo-data:/data + - forgejo-timezone:/etc/timezone:ro + - forgejo-localtime:/etc/localtime:ro + ports: + - 22222:22 + depends_on: + mysql: + condition: service_healthy + healthcheck: + test: ["CMD", "curl", "-f", "http://127.0.0.1:3000"] + interval: 2s + timeout: 10s + retries: 15 + command: >- + bash -c ' + /bin/s6-svscan /etc/s6 & + sleep 10 ; + su -c "forgejo forgejo-cli actions register --secret ${RUNNER_SHARED_SECRET}" git ; + sleep infinity + ' + + mysql: + image: mysql:8 + volumes: + - forgejo-mysql-data:/var/lib/mysql + environment: + - MYSQL_USER=${SERVICE_USER_MYSQL} + - MYSQL_PASSWORD=${SERVICE_PASSWORD_MYSQL} + - MYSQL_DATABASE=${MYSQL_DATABASE} + - MYSQL_ROOT_PASSWORD=${SERVICE_PASSWORD_MYSQLROOT} + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1"] + interval: 5s + timeout: 20s + retries: 10 + + docker-in-docker: + image: docker:dind + hostname: docker + privileged: true + restart: 'unless-stopped' + healthcheck: + disable: true + environment: + DOCKER_TLS_CERTDIR: /certs + DOCKER_HOST: docker-in-docker + volumes: + - forgejo-did-certs:/certs + + runner-register: + image: code.forgejo.org/forgejo/runner:3.5.0 + restart: 'no' + links: + - docker-in-docker + - forgejo + environment: + - DOCKER_HOST=tcp://docker-in-docker:2376 + - RUNNER_SHARED_SECRET=${RUNNER_SHARED_SECRET} + volumes: + - forgejo-runner-data:/data + - forgejo-timezone:/etc/timezone:ro + - forgejo-localtime:/etc/localtime:ro + healthcheck: + disable: true + user: 0:0 + command: >- + bash -ec ' + while : ; do + forgejo-runner create-runner-file --connect --instance http://forgejo:3000 --name runner --secret ${RUNNER_SHARED_SECRET} && break ; + sleep 1 ; + done ; + sed -i -e "s|\"labels\": null|\"labels\": [\"docker:docker://node:20-bookworm\", \"ubuntu-22.04:docker://catthehacker/ubuntu:act-22.04\"]|" .runner ; + forgejo-runner generate-config > config.yml ; + sed -i -e "s|network: .*|network: host|" config.yml ; + sed -i -e "s|^ envs:$$| envs:\n DOCKER_HOST: tcp://docker:2376\n DOCKER_TLS_VERIFY: 1\n DOCKER_CERT_PATH: /certs/client|" config.yml ; + sed -i -e "s|^ options:| options: -v /certs/client:/certs/client|" config.yml ; + sed -i -e "s| valid_volumes: \[\]$$| valid_volumes:\n - /certs/client|" config.yml ; + chown -R 1000:1000 /data ; + exit 0 + ' + + runner: + image: code.forgejo.org/forgejo/runner:3.5.0 + links: + - docker-in-docker + - forgejo + depends_on: + docker-in-docker: + condition: service_started + environment: + - DOCKER_HOST=tcp://docker:2376 + - DOCKER_CERT_PATH=/certs/client + - DOCKER_TLS_VERIFY=1 + user: 1000:1000 + volumes: + - forgejo-runner-data:/data + - forgejo-did-certs:/certs + - forgejo-timezone:/etc/timezone:ro + - forgejo-localtime:/etc/localtime:ro + restart: 'unless-stopped' + healthcheck: + disable: true + command: >- + bash -c ' + while : ; do test -w .runner && forgejo-runner --config config.yml daemon ; sleep 1 ; done + ' \ No newline at end of file diff --git a/templates/compose/forgejo-with-runner-with-postgresql.yaml b/templates/compose/forgejo-with-runner-with-postgresql.yaml new file mode 100644 index 000000000..590ba7617 --- /dev/null +++ b/templates/compose/forgejo-with-runner-with-postgresql.yaml @@ -0,0 +1,127 @@ +# documentation: https://forgejo.org/docs +# slogan: Forgejo is a self-hosted lightweight software forge. Easy to install and low maintenance, it just does the job. +# tags: version control, collaboration, code, hosting, lightweight, runner, actions +# logo: svgs/forgejo.svg + +services: + forgejo: + image: codeberg.org/forgejo/forgejo:7 + environment: + - SERVICE_FQDN_FORGEJO_3000 + - RUNNER_SHARED_SECRET=${RUNNER_SHARED_SECRET} + - USER_UID=1000 + - USER_GID=1000 + - DB_TYPE=postgres + - HOST=postgresql + - NAME=${POSTGRESQL_DATABASE-forgejo} + - USER=$SERVICE_USER_POSTGRESQL + - PASSWD=$SERVICE_PASSWORD_POSTGRESQL + - FORGEJO__repository__ENABLE_PUSH_CREATE_USER=true + - FORGEJO__repository__DEFAULT_PUSH_CREATE_PRIVATE=false + - FORGEJO__repository__DEFAULT_REPO_UNITS=repo.code,repo.actions + volumes: + - forgejo-data:/data + - forgejo-timezone:/etc/timezone:ro + - forgejo-localtime:/etc/localtime:ro + ports: + - 22222:22 + depends_on: + postgresql: + condition: service_healthy + healthcheck: + test: ["CMD", "curl", "-f", "http://127.0.0.1:3000"] + interval: 2s + timeout: 10s + retries: 15 + command: >- + bash -c ' + /bin/s6-svscan /etc/s6 & + sleep 10 ; + su -c "forgejo forgejo-cli actions register --secret ${RUNNER_SHARED_SECRET}" git ; + sleep infinity + ' + + postgresql: + image: postgres:16-alpine + volumes: + - forgejo-postgresql-data:/var/lib/postgresql/data + environment: + - POSTGRES_USER=${SERVICE_USER_POSTGRESQL} + - POSTGRES_PASSWORD=${SERVICE_PASSWORD_POSTGRESQL} + - POSTGRES_DB=${POSTGRESQL_DATABASE} + healthcheck: + test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"] + interval: 5s + timeout: 20s + retries: 10 + + docker-in-docker: + image: docker:dind + hostname: docker + privileged: true + restart: 'unless-stopped' + healthcheck: + disable: true + environment: + DOCKER_TLS_CERTDIR: /certs + DOCKER_HOST: docker-in-docker + volumes: + - forgejo-did-certs:/certs + + runner-register: + image: code.forgejo.org/forgejo/runner:3.5.0 + restart: 'no' + links: + - docker-in-docker + - forgejo + environment: + - DOCKER_HOST=tcp://docker-in-docker:2376 + - RUNNER_SHARED_SECRET=${RUNNER_SHARED_SECRET} + volumes: + - forgejo-runner-data:/data + - forgejo-timezone:/etc/timezone:ro + - forgejo-localtime:/etc/localtime:ro + healthcheck: + disable: true + user: 0:0 + command: >- + bash -ec ' + while : ; do + forgejo-runner create-runner-file --connect --instance http://forgejo:3000 --name runner --secret ${RUNNER_SHARED_SECRET} && break ; + sleep 1 ; + done ; + sed -i -e "s|\"labels\": null|\"labels\": [\"docker:docker://node:20-bookworm\", \"ubuntu-22.04:docker://catthehacker/ubuntu:act-22.04\"]|" .runner ; + forgejo-runner generate-config > config.yml ; + sed -i -e "s|network: .*|network: host|" config.yml ; + sed -i -e "s|^ envs:$$| envs:\n DOCKER_HOST: tcp://docker:2376\n DOCKER_TLS_VERIFY: 1\n DOCKER_CERT_PATH: /certs/client|" config.yml ; + sed -i -e "s|^ options:| options: -v /certs/client:/certs/client|" config.yml ; + sed -i -e "s| valid_volumes: \[\]$$| valid_volumes:\n - /certs/client|" config.yml ; + chown -R 1000:1000 /data ; + exit 0 + ' + + runner: + image: code.forgejo.org/forgejo/runner:3.5.0 + links: + - docker-in-docker + - forgejo + depends_on: + docker-in-docker: + condition: service_started + environment: + - DOCKER_HOST=tcp://docker:2376 + - DOCKER_CERT_PATH=/certs/client + - DOCKER_TLS_VERIFY=1 + user: 1000:1000 + volumes: + - forgejo-runner-data:/data + - forgejo-did-certs:/certs + - forgejo-timezone:/etc/timezone:ro + - forgejo-localtime:/etc/localtime:ro + restart: 'unless-stopped' + healthcheck: + disable: true + command: >- + bash -c ' + while : ; do test -w .runner && forgejo-runner --config config.yml daemon ; sleep 1 ; done + ' \ No newline at end of file diff --git a/templates/compose/forgejo-with-runner.yaml b/templates/compose/forgejo-with-runner.yaml new file mode 100644 index 000000000..ea476efa9 --- /dev/null +++ b/templates/compose/forgejo-with-runner.yaml @@ -0,0 +1,105 @@ +# documentation: https://forgejo.org/docs +# slogan: Forgejo is a self-hosted lightweight software forge. Easy to install and low maintenance, it just does the job. +# tags: version control, collaboration, code, hosting, lightweight, runner, actions +# logo: svgs/forgejo.svg + +services: + forgejo: + image: codeberg.org/forgejo/forgejo:7 + environment: + - SERVICE_FQDN_FORGEJO_3000 + - RUNNER_SHARED_SECRET=${RUNNER_SHARED_SECRET} + - USER_UID=1000 + - USER_GID=1000 + - FORGEJO__repository__ENABLE_PUSH_CREATE_USER=true + - FORGEJO__repository__DEFAULT_PUSH_CREATE_PRIVATE=false + - FORGEJO__repository__DEFAULT_REPO_UNITS=repo.code,repo.actions + volumes: + - forgejo-data:/data + - forgejo-timezone:/etc/timezone:ro + - forgejo-localtime:/etc/localtime:ro + ports: + - 22222:22 + healthcheck: + test: ["CMD", "curl", "-f", "http://127.0.0.1:3000"] + interval: 2s + timeout: 10s + retries: 15 + command: >- + bash -c ' + /bin/s6-svscan /etc/s6 & + sleep 10 ; + su -c "forgejo forgejo-cli actions register --secret ${RUNNER_SHARED_SECRET}" git ; + sleep infinity + ' + + docker-in-docker: + image: docker:dind + hostname: docker + privileged: true + restart: 'unless-stopped' + healthcheck: + disable: true + environment: + DOCKER_TLS_CERTDIR: /certs + DOCKER_HOST: docker-in-docker + volumes: + - forgejo-did-certs:/certs + + runner-register: + image: code.forgejo.org/forgejo/runner:3.5.0 + restart: 'no' + links: + - docker-in-docker + - forgejo + environment: + - DOCKER_HOST=tcp://docker-in-docker:2376 + - RUNNER_SHARED_SECRET=${RUNNER_SHARED_SECRET} + volumes: + - forgejo-runner-data:/data + - forgejo-timezone:/etc/timezone:ro + - forgejo-localtime:/etc/localtime:ro + healthcheck: + disable: true + user: 0:0 + command: >- + bash -ec ' + while : ; do + forgejo-runner create-runner-file --connect --instance http://forgejo:3000 --name runner --secret ${RUNNER_SHARED_SECRET} && break ; + sleep 1 ; + done ; + sed -i -e "s|\"labels\": null|\"labels\": [\"docker:docker://node:20-bookworm\", \"ubuntu-22.04:docker://catthehacker/ubuntu:act-22.04\"]|" .runner ; + forgejo-runner generate-config > config.yml ; + sed -i -e "s|network: .*|network: host|" config.yml ; + sed -i -e "s|^ envs:$$| envs:\n DOCKER_HOST: tcp://docker:2376\n DOCKER_TLS_VERIFY: 1\n DOCKER_CERT_PATH: /certs/client|" config.yml ; + sed -i -e "s|^ options:| options: -v /certs/client:/certs/client|" config.yml ; + sed -i -e "s| valid_volumes: \[\]$$| valid_volumes:\n - /certs/client|" config.yml ; + chown -R 1000:1000 /data ; + exit 0 + ' + + runner: + image: code.forgejo.org/forgejo/runner:3.5.0 + links: + - docker-in-docker + - forgejo + depends_on: + docker-in-docker: + condition: service_started + environment: + - DOCKER_HOST=tcp://docker:2376 + - DOCKER_CERT_PATH=/certs/client + - DOCKER_TLS_VERIFY=1 + user: 1000:1000 + volumes: + - forgejo-runner-data:/data + - forgejo-did-certs:/certs + - forgejo-timezone:/etc/timezone:ro + - forgejo-localtime:/etc/localtime:ro + restart: 'unless-stopped' + healthcheck: + disable: true + command: >- + bash -c ' + while : ; do test -w .runner && forgejo-runner --config config.yml daemon ; sleep 1 ; done + ' \ No newline at end of file diff --git a/templates/compose/forgejo.yaml b/templates/compose/forgejo.yaml new file mode 100644 index 000000000..fe633d609 --- /dev/null +++ b/templates/compose/forgejo.yaml @@ -0,0 +1,22 @@ +# documentation: https://forgejo.org/docs +# slogan: Forgejo is a self-hosted lightweight software forge. Easy to install and low maintenance, it just does the job. +# tags: version control, collaboration, code, hosting, lightweight +# logo: svgs/forgejo.svg + +services: + forgejo: + image: codeberg.org/forgejo/forgejo:7 + environment: + - USER_UID=1000 + - USER_GID=1000 + ports: + - 22222:22 + volumes: + - forgejo-data:/data + - forgejo-timezone:/etc/timezone:ro + - forgejo-localtime:/etc/localtime:ro + healthcheck: + test: ["CMD", "curl", "-f", "http://127.0.0.1:3000"] + interval: 2s + timeout: 10s + retries: 15 \ No newline at end of file From c1612a9e88d67270a8a498feb0b5568eab520def Mon Sep 17 00:00:00 2001 From: Italo Date: Sat, 29 Jun 2024 23:12:43 -0400 Subject: [PATCH 009/863] Fixes environment variables --- templates/compose/forgejo-with-mariadb.yaml | 12 +++++++----- templates/compose/forgejo-with-mysql.yaml | 11 ++++++----- templates/compose/forgejo-with-postgresql.yaml | 12 +++++++----- .../compose/forgejo-with-runner-mariadb.yaml | 15 ++++++++------- .../compose/forgejo-with-runner-with-mysql.yaml | 15 ++++++++------- .../forgejo-with-runner-with-postgresql.yaml | 15 ++++++++------- templates/compose/forgejo-with-runner.yaml | 5 +++-- templates/compose/forgejo.yaml | 2 ++ 8 files changed, 49 insertions(+), 38 deletions(-) diff --git a/templates/compose/forgejo-with-mariadb.yaml b/templates/compose/forgejo-with-mariadb.yaml index e1d49515b..6b58b683c 100644 --- a/templates/compose/forgejo-with-mariadb.yaml +++ b/templates/compose/forgejo-with-mariadb.yaml @@ -7,13 +7,15 @@ services: forgejo: image: codeberg.org/forgejo/forgejo:7 environment: + - SERVICE_FQDN_FORGEJO_3000 + - FORGEJO__server__ROOT_URL=${SERVICE_FQDN_FORGEJO} - USER_UID=1000 - USER_GID=1000 - - DB_TYPE=mysql - - HOST=mariadb - - NAME=${MYSQL_DATABASE-forgejo} - - USER=$SERVICE_USER_MYSQL - - PASSWD=$SERVICE_PASSWORD_MYSQL + - FORGEJO__database__DB_TYPE=mysql + - FORGEJO__database__HOST=mariadb + - FORGEJO__database__NAME=${MYSQL_DATABASE-forgejo} + - FORGEJO__database__USER=$SERVICE_USER_MYSQL + - FORGEJO__database__PASSWD=$SERVICE_PASSWORD_MYSQL volumes: - forgejo-data:/data - forgejo-timezone:/etc/timezone:ro diff --git a/templates/compose/forgejo-with-mysql.yaml b/templates/compose/forgejo-with-mysql.yaml index f46b2c447..2029ba39f 100644 --- a/templates/compose/forgejo-with-mysql.yaml +++ b/templates/compose/forgejo-with-mysql.yaml @@ -8,13 +8,14 @@ services: image: codeberg.org/forgejo/forgejo:7 environment: - SERVICE_FQDN_FORGEJO_3000 + - FORGEJO__server__ROOT_URL=${SERVICE_FQDN_FORGEJO} - USER_UID=1000 - USER_GID=1000 - - DB_TYPE=mysql - - HOST=mysql - - NAME=${MYSQL_DATABASE-forgejo} - - USER=$SERVICE_USER_MYSQL - - PASSWD=$SERVICE_PASSWORD_MYSQL + - FORGEJO__database__DB_TYPE=mysql + - FORGEJO__database__HOST=mysql + - FORGEJO__database__NAME=${MYSQL_DATABASE-forgejo} + - FORGEJO__database__USER=$SERVICE_USER_MYSQL + - FORGEJO__database__PASSWD=$SERVICE_PASSWORD_MYSQL volumes: - forgejo-data:/data - forgejo-timezone:/etc/timezone:ro diff --git a/templates/compose/forgejo-with-postgresql.yaml b/templates/compose/forgejo-with-postgresql.yaml index 4c39fc1b9..4549ab70f 100644 --- a/templates/compose/forgejo-with-postgresql.yaml +++ b/templates/compose/forgejo-with-postgresql.yaml @@ -7,13 +7,15 @@ services: forgejo: image: codeberg.org/forgejo/forgejo:7 environment: + - SERVICE_FQDN_FORGEJO_3000 + - FORGEJO__server__ROOT_URL=${SERVICE_FQDN_FORGEJO} - USER_UID=1000 - USER_GID=1000 - - DB_TYPE=postgres - - HOST=postgresql - - NAME=${POSTGRESQL_DATABASE-forgejo} - - USER=$SERVICE_USER_POSTGRESQL - - PASSWD=$SERVICE_PASSWORD_POSTGRESQL + - FORGEJO__database__DB_TYPE=postgres + - FORGEJO__database__HOST=postgresql + - FORGEJO__database__NAME=${POSTGRESQL_DATABASE-forgejo} + - FORGEJO__database__USER=$SERVICE_USER_POSTGRESQL + - FORGEJO__database__PASSWD=$SERVICE_PASSWORD_POSTGRESQL volumes: - forgejo-data:/data - forgejo-timezone:/etc/timezone:ro diff --git a/templates/compose/forgejo-with-runner-mariadb.yaml b/templates/compose/forgejo-with-runner-mariadb.yaml index 1f4b932d1..973d5e900 100644 --- a/templates/compose/forgejo-with-runner-mariadb.yaml +++ b/templates/compose/forgejo-with-runner-mariadb.yaml @@ -1,6 +1,6 @@ # documentation: https://forgejo.org/docs # slogan: Forgejo is a self-hosted lightweight software forge. Easy to install and low maintenance, it just does the job. -# tags: version control, collaboration, code, hosting, lightweight, runner, actions +# tags: version control, collaboration, code, hosting, lightweight, runner, mariadb, actions, cicd, ci # logo: svgs/forgejo.svg services: @@ -8,14 +8,15 @@ services: image: codeberg.org/forgejo/forgejo:7 environment: - SERVICE_FQDN_FORGEJO_3000 - - RUNNER_SHARED_SECRET=${RUNNER_SHARED_SECRET} + - FORGEJO__server__ROOT_URL=${SERVICE_FQDN_FORGEJO} - USER_UID=1000 - USER_GID=1000 - - DB_TYPE=mysql - - HOST=mariadb - - NAME=${MYSQL_DATABASE-forgejo} - - USER=$SERVICE_USER_MYSQL - - PASSWD=$SERVICE_PASSWORD_MYSQL + - FORGEJO__database__DB_TYPE=mysql + - FORGEJO__database__HOST=mariadb + - FORGEJO__database__NAME=${MYSQL_DATABASE-forgejo} + - FORGEJO__database__USER=$SERVICE_USER_MYSQL + - FORGEJO__database__PASSWD=$SERVICE_PASSWORD_MYSQL + - RUNNER_SHARED_SECRET=${RUNNER_SHARED_SECRET-0000000000000000000000000000000000000000} - FORGEJO__repository__ENABLE_PUSH_CREATE_USER=true - FORGEJO__repository__DEFAULT_PUSH_CREATE_PRIVATE=false - FORGEJO__repository__DEFAULT_REPO_UNITS=repo.code,repo.actions diff --git a/templates/compose/forgejo-with-runner-with-mysql.yaml b/templates/compose/forgejo-with-runner-with-mysql.yaml index 0dd87767e..3d0cae916 100644 --- a/templates/compose/forgejo-with-runner-with-mysql.yaml +++ b/templates/compose/forgejo-with-runner-with-mysql.yaml @@ -1,6 +1,6 @@ # documentation: https://forgejo.org/docs # slogan: Forgejo is a self-hosted lightweight software forge. Easy to install and low maintenance, it just does the job. -# tags: version control, collaboration, code, hosting, lightweight, runner, actions +# tags: version control, collaboration, code, hosting, lightweight, runner, mysql, actions, cicd, ci # logo: svgs/forgejo.svg services: @@ -8,14 +8,15 @@ services: image: codeberg.org/forgejo/forgejo:7 environment: - SERVICE_FQDN_FORGEJO_3000 - - RUNNER_SHARED_SECRET=${RUNNER_SHARED_SECRET} + - FORGEJO__server__ROOT_URL=${SERVICE_FQDN_FORGEJO} - USER_UID=1000 - USER_GID=1000 - - DB_TYPE=mysql - - HOST=mysql - - NAME=${MYSQL_DATABASE-forgejo} - - USER=$SERVICE_USER_MYSQL - - PASSWD=$SERVICE_PASSWORD_MYSQL + - FORGEJO__database__DB_TYPE=mysql + - FORGEJO__database__HOST=mysql + - FORGEJO__database__NAME=${MYSQL_DATABASE-forgejo} + - FORGEJO__database__USER=$SERVICE_USER_MYSQL + - FORGEJO__database__PASSWD=$SERVICE_PASSWORD_MYSQL + - RUNNER_SHARED_SECRET=${RUNNER_SHARED_SECRET-0000000000000000000000000000000000000000} - FORGEJO__repository__ENABLE_PUSH_CREATE_USER=true - FORGEJO__repository__DEFAULT_PUSH_CREATE_PRIVATE=false - FORGEJO__repository__DEFAULT_REPO_UNITS=repo.code,repo.actions diff --git a/templates/compose/forgejo-with-runner-with-postgresql.yaml b/templates/compose/forgejo-with-runner-with-postgresql.yaml index 590ba7617..040626f9f 100644 --- a/templates/compose/forgejo-with-runner-with-postgresql.yaml +++ b/templates/compose/forgejo-with-runner-with-postgresql.yaml @@ -1,6 +1,6 @@ # documentation: https://forgejo.org/docs # slogan: Forgejo is a self-hosted lightweight software forge. Easy to install and low maintenance, it just does the job. -# tags: version control, collaboration, code, hosting, lightweight, runner, actions +# tags: version control, collaboration, code, hosting, lightweight, runner, postresql, actions, cicd, ci # logo: svgs/forgejo.svg services: @@ -8,14 +8,15 @@ services: image: codeberg.org/forgejo/forgejo:7 environment: - SERVICE_FQDN_FORGEJO_3000 - - RUNNER_SHARED_SECRET=${RUNNER_SHARED_SECRET} + - FORGEJO__server__ROOT_URL=${SERVICE_FQDN_FORGEJO} - USER_UID=1000 - USER_GID=1000 - - DB_TYPE=postgres - - HOST=postgresql - - NAME=${POSTGRESQL_DATABASE-forgejo} - - USER=$SERVICE_USER_POSTGRESQL - - PASSWD=$SERVICE_PASSWORD_POSTGRESQL + - FORGEJO__database__DB_TYPE=postgres + - FORGEJO__database__HOST=postgresql + - FORGEJO__database__NAME=${POSTGRESQL_DATABASE-forgejo} + - FORGEJO__database__USER=$SERVICE_USER_POSTGRESQL + - FORGEJO__database__PASSWD=$SERVICE_PASSWORD_POSTGRESQL + - RUNNER_SHARED_SECRET=${RUNNER_SHARED_SECRET-0000000000000000000000000000000000000000} - FORGEJO__repository__ENABLE_PUSH_CREATE_USER=true - FORGEJO__repository__DEFAULT_PUSH_CREATE_PRIVATE=false - FORGEJO__repository__DEFAULT_REPO_UNITS=repo.code,repo.actions diff --git a/templates/compose/forgejo-with-runner.yaml b/templates/compose/forgejo-with-runner.yaml index ea476efa9..e375279be 100644 --- a/templates/compose/forgejo-with-runner.yaml +++ b/templates/compose/forgejo-with-runner.yaml @@ -1,6 +1,6 @@ # documentation: https://forgejo.org/docs # slogan: Forgejo is a self-hosted lightweight software forge. Easy to install and low maintenance, it just does the job. -# tags: version control, collaboration, code, hosting, lightweight, runner, actions +# tags: version control, collaboration, code, hosting, lightweight, runner, actions, cicd, ci # logo: svgs/forgejo.svg services: @@ -8,9 +8,10 @@ services: image: codeberg.org/forgejo/forgejo:7 environment: - SERVICE_FQDN_FORGEJO_3000 - - RUNNER_SHARED_SECRET=${RUNNER_SHARED_SECRET} + - FORGEJO__server__ROOT_URL=${SERVICE_FQDN_FORGEJO} - USER_UID=1000 - USER_GID=1000 + - RUNNER_SHARED_SECRET=${RUNNER_SHARED_SECRET-0000000000000000000000000000000000000000} - FORGEJO__repository__ENABLE_PUSH_CREATE_USER=true - FORGEJO__repository__DEFAULT_PUSH_CREATE_PRIVATE=false - FORGEJO__repository__DEFAULT_REPO_UNITS=repo.code,repo.actions diff --git a/templates/compose/forgejo.yaml b/templates/compose/forgejo.yaml index fe633d609..3f13f1323 100644 --- a/templates/compose/forgejo.yaml +++ b/templates/compose/forgejo.yaml @@ -7,6 +7,8 @@ services: forgejo: image: codeberg.org/forgejo/forgejo:7 environment: + - SERVICE_FQDN_FORGEJO_3000 + - FORGEJO__server__ROOT_URL=${SERVICE_FQDN_FORGEJO} - USER_UID=1000 - USER_GID=1000 ports: From 204aaf5dfa10935ebd699040de4ac52d56e333ca Mon Sep 17 00:00:00 2001 From: Italo Date: Sat, 29 Jun 2024 23:13:45 -0400 Subject: [PATCH 010/863] Fixes file name --- ...-runner-mariadb.yaml => forgejo-with-runner-with-mariadb.yaml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename templates/compose/{forgejo-with-runner-mariadb.yaml => forgejo-with-runner-with-mariadb.yaml} (100%) diff --git a/templates/compose/forgejo-with-runner-mariadb.yaml b/templates/compose/forgejo-with-runner-with-mariadb.yaml similarity index 100% rename from templates/compose/forgejo-with-runner-mariadb.yaml rename to templates/compose/forgejo-with-runner-with-mariadb.yaml From 807304c50b395dff677ca0a37ecfbff63e1f7338 Mon Sep 17 00:00:00 2001 From: Italo Date: Sat, 29 Jun 2024 23:29:46 -0400 Subject: [PATCH 011/863] Adds healthcheck for DID --- templates/compose/forgejo-with-runner-with-mariadb.yaml | 5 ++++- templates/compose/forgejo-with-runner-with-mysql.yaml | 5 ++++- templates/compose/forgejo-with-runner-with-postgresql.yaml | 5 ++++- templates/compose/forgejo-with-runner.yaml | 5 ++++- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/templates/compose/forgejo-with-runner-with-mariadb.yaml b/templates/compose/forgejo-with-runner-with-mariadb.yaml index 973d5e900..805aa0d9f 100644 --- a/templates/compose/forgejo-with-runner-with-mariadb.yaml +++ b/templates/compose/forgejo-with-runner-with-mariadb.yaml @@ -63,7 +63,10 @@ services: privileged: true restart: 'unless-stopped' healthcheck: - disable: true + test: ["CMD", "nc", "-z", "127.0.0.1", "2376"] + interval: 10s + timeout: 30s + retries: 10 environment: DOCKER_TLS_CERTDIR: /certs DOCKER_HOST: docker-in-docker diff --git a/templates/compose/forgejo-with-runner-with-mysql.yaml b/templates/compose/forgejo-with-runner-with-mysql.yaml index 3d0cae916..9487694af 100644 --- a/templates/compose/forgejo-with-runner-with-mysql.yaml +++ b/templates/compose/forgejo-with-runner-with-mysql.yaml @@ -63,7 +63,10 @@ services: privileged: true restart: 'unless-stopped' healthcheck: - disable: true + test: ["CMD", "nc", "-z", "127.0.0.1", "2376"] + interval: 10s + timeout: 30s + retries: 10 environment: DOCKER_TLS_CERTDIR: /certs DOCKER_HOST: docker-in-docker diff --git a/templates/compose/forgejo-with-runner-with-postgresql.yaml b/templates/compose/forgejo-with-runner-with-postgresql.yaml index 040626f9f..bac4a4681 100644 --- a/templates/compose/forgejo-with-runner-with-postgresql.yaml +++ b/templates/compose/forgejo-with-runner-with-postgresql.yaml @@ -62,7 +62,10 @@ services: privileged: true restart: 'unless-stopped' healthcheck: - disable: true + test: ["CMD", "nc", "-z", "127.0.0.1", "2376"] + interval: 10s + timeout: 30s + retries: 10 environment: DOCKER_TLS_CERTDIR: /certs DOCKER_HOST: docker-in-docker diff --git a/templates/compose/forgejo-with-runner.yaml b/templates/compose/forgejo-with-runner.yaml index e375279be..7865e8fa4 100644 --- a/templates/compose/forgejo-with-runner.yaml +++ b/templates/compose/forgejo-with-runner.yaml @@ -40,7 +40,10 @@ services: privileged: true restart: 'unless-stopped' healthcheck: - disable: true + test: ["CMD", "nc", "-z", "127.0.0.1", "2376"] + interval: 10s + timeout: 30s + retries: 10 environment: DOCKER_TLS_CERTDIR: /certs DOCKER_HOST: docker-in-docker From 793f91e7fb1fa265c2042ed120749122c7d9b810 Mon Sep 17 00:00:00 2001 From: Italo Date: Sat, 29 Jun 2024 23:42:26 -0400 Subject: [PATCH 012/863] Adds healthcheck for runner --- templates/compose/forgejo-with-runner-with-mariadb.yaml | 5 ++++- templates/compose/forgejo-with-runner-with-mysql.yaml | 5 ++++- templates/compose/forgejo-with-runner-with-postgresql.yaml | 5 ++++- templates/compose/forgejo-with-runner.yaml | 5 ++++- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/templates/compose/forgejo-with-runner-with-mariadb.yaml b/templates/compose/forgejo-with-runner-with-mariadb.yaml index 805aa0d9f..b137c9382 100644 --- a/templates/compose/forgejo-with-runner-with-mariadb.yaml +++ b/templates/compose/forgejo-with-runner-with-mariadb.yaml @@ -125,7 +125,10 @@ services: - forgejo-localtime:/etc/localtime:ro restart: 'unless-stopped' healthcheck: - disable: true + test: ["CMD", "pgrep", "forgejo-runner"] + interval: 10s + timeout: 30s + retries: 10 command: >- bash -c ' while : ; do test -w .runner && forgejo-runner --config config.yml daemon ; sleep 1 ; done diff --git a/templates/compose/forgejo-with-runner-with-mysql.yaml b/templates/compose/forgejo-with-runner-with-mysql.yaml index 9487694af..21c62c06d 100644 --- a/templates/compose/forgejo-with-runner-with-mysql.yaml +++ b/templates/compose/forgejo-with-runner-with-mysql.yaml @@ -125,7 +125,10 @@ services: - forgejo-localtime:/etc/localtime:ro restart: 'unless-stopped' healthcheck: - disable: true + test: ["CMD", "pgrep", "forgejo-runner"] + interval: 10s + timeout: 30s + retries: 10 command: >- bash -c ' while : ; do test -w .runner && forgejo-runner --config config.yml daemon ; sleep 1 ; done diff --git a/templates/compose/forgejo-with-runner-with-postgresql.yaml b/templates/compose/forgejo-with-runner-with-postgresql.yaml index bac4a4681..486c7a462 100644 --- a/templates/compose/forgejo-with-runner-with-postgresql.yaml +++ b/templates/compose/forgejo-with-runner-with-postgresql.yaml @@ -124,7 +124,10 @@ services: - forgejo-localtime:/etc/localtime:ro restart: 'unless-stopped' healthcheck: - disable: true + test: ["CMD", "pgrep", "forgejo-runner"] + interval: 10s + timeout: 30s + retries: 10 command: >- bash -c ' while : ; do test -w .runner && forgejo-runner --config config.yml daemon ; sleep 1 ; done diff --git a/templates/compose/forgejo-with-runner.yaml b/templates/compose/forgejo-with-runner.yaml index 7865e8fa4..2e526cbde 100644 --- a/templates/compose/forgejo-with-runner.yaml +++ b/templates/compose/forgejo-with-runner.yaml @@ -102,7 +102,10 @@ services: - forgejo-localtime:/etc/localtime:ro restart: 'unless-stopped' healthcheck: - disable: true + test: ["CMD", "pgrep", "forgejo-runner"] + interval: 10s + timeout: 30s + retries: 10 command: >- bash -c ' while : ; do test -w .runner && forgejo-runner --config config.yml daemon ; sleep 1 ; done From ea81d8ecfe811d31c6b914031e0d8d0c713e218f Mon Sep 17 00:00:00 2001 From: Italo Date: Thu, 4 Jul 2024 19:46:35 -0400 Subject: [PATCH 013/863] Adds external migration configuration --- templates/compose/forgejo-with-mariadb.yaml | 2 ++ templates/compose/forgejo-with-mysql.yaml | 2 ++ templates/compose/forgejo-with-postgresql.yaml | 2 ++ templates/compose/forgejo-with-runner-with-mariadb.yaml | 2 ++ templates/compose/forgejo-with-runner-with-mysql.yaml | 2 ++ templates/compose/forgejo-with-runner-with-postgresql.yaml | 2 ++ templates/compose/forgejo-with-runner.yaml | 2 ++ templates/compose/forgejo.yaml | 2 ++ 8 files changed, 16 insertions(+) diff --git a/templates/compose/forgejo-with-mariadb.yaml b/templates/compose/forgejo-with-mariadb.yaml index 6b58b683c..92e7843f1 100644 --- a/templates/compose/forgejo-with-mariadb.yaml +++ b/templates/compose/forgejo-with-mariadb.yaml @@ -9,6 +9,8 @@ services: environment: - SERVICE_FQDN_FORGEJO_3000 - FORGEJO__server__ROOT_URL=${SERVICE_FQDN_FORGEJO} + - FORGEJO__migrations__ALLOWED_DOMAINS=${FORGEJO__migrations__ALLOWED_DOMAINS} + - FORGEJO__migrations__ALLOW_LOCALNETWORKS=${FORGEJO__migrations__ALLOW_LOCALNETWORKS-false} - USER_UID=1000 - USER_GID=1000 - FORGEJO__database__DB_TYPE=mysql diff --git a/templates/compose/forgejo-with-mysql.yaml b/templates/compose/forgejo-with-mysql.yaml index 2029ba39f..9b2359c08 100644 --- a/templates/compose/forgejo-with-mysql.yaml +++ b/templates/compose/forgejo-with-mysql.yaml @@ -9,6 +9,8 @@ services: environment: - SERVICE_FQDN_FORGEJO_3000 - FORGEJO__server__ROOT_URL=${SERVICE_FQDN_FORGEJO} + - FORGEJO__migrations__ALLOWED_DOMAINS=${FORGEJO__migrations__ALLOWED_DOMAINS} + - FORGEJO__migrations__ALLOW_LOCALNETWORKS=${FORGEJO__migrations__ALLOW_LOCALNETWORKS-false} - USER_UID=1000 - USER_GID=1000 - FORGEJO__database__DB_TYPE=mysql diff --git a/templates/compose/forgejo-with-postgresql.yaml b/templates/compose/forgejo-with-postgresql.yaml index 4549ab70f..2a7596074 100644 --- a/templates/compose/forgejo-with-postgresql.yaml +++ b/templates/compose/forgejo-with-postgresql.yaml @@ -9,6 +9,8 @@ services: environment: - SERVICE_FQDN_FORGEJO_3000 - FORGEJO__server__ROOT_URL=${SERVICE_FQDN_FORGEJO} + - FORGEJO__migrations__ALLOWED_DOMAINS=${FORGEJO__migrations__ALLOWED_DOMAINS} + - FORGEJO__migrations__ALLOW_LOCALNETWORKS=${FORGEJO__migrations__ALLOW_LOCALNETWORKS-false} - USER_UID=1000 - USER_GID=1000 - FORGEJO__database__DB_TYPE=postgres diff --git a/templates/compose/forgejo-with-runner-with-mariadb.yaml b/templates/compose/forgejo-with-runner-with-mariadb.yaml index b137c9382..372da3866 100644 --- a/templates/compose/forgejo-with-runner-with-mariadb.yaml +++ b/templates/compose/forgejo-with-runner-with-mariadb.yaml @@ -9,6 +9,8 @@ services: environment: - SERVICE_FQDN_FORGEJO_3000 - FORGEJO__server__ROOT_URL=${SERVICE_FQDN_FORGEJO} + - FORGEJO__migrations__ALLOWED_DOMAINS=${FORGEJO__migrations__ALLOWED_DOMAINS} + - FORGEJO__migrations__ALLOW_LOCALNETWORKS=${FORGEJO__migrations__ALLOW_LOCALNETWORKS-false} - USER_UID=1000 - USER_GID=1000 - FORGEJO__database__DB_TYPE=mysql diff --git a/templates/compose/forgejo-with-runner-with-mysql.yaml b/templates/compose/forgejo-with-runner-with-mysql.yaml index 21c62c06d..c7abc3193 100644 --- a/templates/compose/forgejo-with-runner-with-mysql.yaml +++ b/templates/compose/forgejo-with-runner-with-mysql.yaml @@ -9,6 +9,8 @@ services: environment: - SERVICE_FQDN_FORGEJO_3000 - FORGEJO__server__ROOT_URL=${SERVICE_FQDN_FORGEJO} + - FORGEJO__migrations__ALLOWED_DOMAINS=${FORGEJO__migrations__ALLOWED_DOMAINS} + - FORGEJO__migrations__ALLOW_LOCALNETWORKS=${FORGEJO__migrations__ALLOW_LOCALNETWORKS-false} - USER_UID=1000 - USER_GID=1000 - FORGEJO__database__DB_TYPE=mysql diff --git a/templates/compose/forgejo-with-runner-with-postgresql.yaml b/templates/compose/forgejo-with-runner-with-postgresql.yaml index 486c7a462..16c9278ff 100644 --- a/templates/compose/forgejo-with-runner-with-postgresql.yaml +++ b/templates/compose/forgejo-with-runner-with-postgresql.yaml @@ -9,6 +9,8 @@ services: environment: - SERVICE_FQDN_FORGEJO_3000 - FORGEJO__server__ROOT_URL=${SERVICE_FQDN_FORGEJO} + - FORGEJO__migrations__ALLOWED_DOMAINS=${FORGEJO__migrations__ALLOWED_DOMAINS} + - FORGEJO__migrations__ALLOW_LOCALNETWORKS=${FORGEJO__migrations__ALLOW_LOCALNETWORKS-false} - USER_UID=1000 - USER_GID=1000 - FORGEJO__database__DB_TYPE=postgres diff --git a/templates/compose/forgejo-with-runner.yaml b/templates/compose/forgejo-with-runner.yaml index 2e526cbde..9e54fdda0 100644 --- a/templates/compose/forgejo-with-runner.yaml +++ b/templates/compose/forgejo-with-runner.yaml @@ -9,6 +9,8 @@ services: environment: - SERVICE_FQDN_FORGEJO_3000 - FORGEJO__server__ROOT_URL=${SERVICE_FQDN_FORGEJO} + - FORGEJO__migrations__ALLOWED_DOMAINS=${FORGEJO__migrations__ALLOWED_DOMAINS} + - FORGEJO__migrations__ALLOW_LOCALNETWORKS=${FORGEJO__migrations__ALLOW_LOCALNETWORKS-false} - USER_UID=1000 - USER_GID=1000 - RUNNER_SHARED_SECRET=${RUNNER_SHARED_SECRET-0000000000000000000000000000000000000000} diff --git a/templates/compose/forgejo.yaml b/templates/compose/forgejo.yaml index 3f13f1323..bb6846679 100644 --- a/templates/compose/forgejo.yaml +++ b/templates/compose/forgejo.yaml @@ -9,6 +9,8 @@ services: environment: - SERVICE_FQDN_FORGEJO_3000 - FORGEJO__server__ROOT_URL=${SERVICE_FQDN_FORGEJO} + - FORGEJO__migrations__ALLOWED_DOMAINS=${FORGEJO__migrations__ALLOWED_DOMAINS} + - FORGEJO__migrations__ALLOW_LOCALNETWORKS=${FORGEJO__migrations__ALLOW_LOCALNETWORKS-false} - USER_UID=1000 - USER_GID=1000 ports: From e1a585c1941b74573ba6ef4a3be6918d2c819382 Mon Sep 17 00:00:00 2001 From: Italo Date: Sat, 13 Jul 2024 23:32:34 -0400 Subject: [PATCH 014/863] Healtcheck done to the process name --- templates/compose/forgejo-with-runner-with-mariadb.yaml | 2 +- templates/compose/forgejo-with-runner-with-mysql.yaml | 2 +- templates/compose/forgejo-with-runner-with-postgresql.yaml | 2 +- templates/compose/forgejo-with-runner.yaml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/templates/compose/forgejo-with-runner-with-mariadb.yaml b/templates/compose/forgejo-with-runner-with-mariadb.yaml index 372da3866..a751ee284 100644 --- a/templates/compose/forgejo-with-runner-with-mariadb.yaml +++ b/templates/compose/forgejo-with-runner-with-mariadb.yaml @@ -65,7 +65,7 @@ services: privileged: true restart: 'unless-stopped' healthcheck: - test: ["CMD", "nc", "-z", "127.0.0.1", "2376"] + test: ["CMD", "pgrep", "dockerd"] interval: 10s timeout: 30s retries: 10 diff --git a/templates/compose/forgejo-with-runner-with-mysql.yaml b/templates/compose/forgejo-with-runner-with-mysql.yaml index c7abc3193..ccc33644f 100644 --- a/templates/compose/forgejo-with-runner-with-mysql.yaml +++ b/templates/compose/forgejo-with-runner-with-mysql.yaml @@ -65,7 +65,7 @@ services: privileged: true restart: 'unless-stopped' healthcheck: - test: ["CMD", "nc", "-z", "127.0.0.1", "2376"] + test: ["CMD", "pgrep", "dockerd"] interval: 10s timeout: 30s retries: 10 diff --git a/templates/compose/forgejo-with-runner-with-postgresql.yaml b/templates/compose/forgejo-with-runner-with-postgresql.yaml index 16c9278ff..0b4dcd3fe 100644 --- a/templates/compose/forgejo-with-runner-with-postgresql.yaml +++ b/templates/compose/forgejo-with-runner-with-postgresql.yaml @@ -64,7 +64,7 @@ services: privileged: true restart: 'unless-stopped' healthcheck: - test: ["CMD", "nc", "-z", "127.0.0.1", "2376"] + test: ["CMD", "pgrep", "dockerd"] interval: 10s timeout: 30s retries: 10 diff --git a/templates/compose/forgejo-with-runner.yaml b/templates/compose/forgejo-with-runner.yaml index 9e54fdda0..abcaa6e7e 100644 --- a/templates/compose/forgejo-with-runner.yaml +++ b/templates/compose/forgejo-with-runner.yaml @@ -42,7 +42,7 @@ services: privileged: true restart: 'unless-stopped' healthcheck: - test: ["CMD", "nc", "-z", "127.0.0.1", "2376"] + test: ["CMD", "pgrep", "dockerd"] interval: 10s timeout: 30s retries: 10 From 633c8253ec1cd8ea51a0d1b18992ec3017aee149 Mon Sep 17 00:00:00 2001 From: Italo Date: Wed, 17 Jul 2024 14:53:45 -0400 Subject: [PATCH 015/863] Adds missing forgejo logo svg --- public/svgs/forgejo.svg | 1 + 1 file changed, 1 insertion(+) create mode 100644 public/svgs/forgejo.svg diff --git a/public/svgs/forgejo.svg b/public/svgs/forgejo.svg new file mode 100644 index 000000000..804b05e28 --- /dev/null +++ b/public/svgs/forgejo.svg @@ -0,0 +1 @@ + \ No newline at end of file From 48886cac84f9d502527f159ccf5bb542aabc5a99 Mon Sep 17 00:00:00 2001 From: Leonardo Cabeza Date: Fri, 19 Jul 2024 16:07:53 -0500 Subject: [PATCH 016/863] feat: add easyappointments service template --- public/svgs/easyappointments.png | Bin 0 -> 25264 bytes templates/compose/easyappointments.yaml | 37 ++++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 public/svgs/easyappointments.png create mode 100644 templates/compose/easyappointments.yaml diff --git a/public/svgs/easyappointments.png b/public/svgs/easyappointments.png new file mode 100644 index 0000000000000000000000000000000000000000..8f00d3353100889943d50ad01df93fa474ce6df6 GIT binary patch literal 25264 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 z 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 o$j=D)|L*($mmforc+Ais(jQ{`u literal 0 HcmV?d00001 diff --git a/templates/compose/easyappointments.yaml b/templates/compose/easyappointments.yaml new file mode 100644 index 000000000..d4b371817 --- /dev/null +++ b/templates/compose/easyappointments.yaml @@ -0,0 +1,37 @@ +# documentation: https://easyappointments.org/ +# slogan: SCHEDULE ANYTHING. - Let's start with easy! Get the best free online appointment scheduler on your server, today. +# tags: calendar, scheduling, database +# logo: svgs/easyappointments.png +# port: 80 + +services: + easyappointments: + image: alextselegidis/easyappointments:latest + restart: unless-stopped + environment: + - SERVICE_FQDN_EASYAPPOINTMENTS_80 + - BASE_URL=${SERVICE_FQDN_EASYAPPOINTMENTS} + - DB_HOST=mysql + - DB_NAME=easyappointments + - DB_USERNAME=root + - DB_PASSWORD=${SERVICE_PASSWORD_EASYAPPOINTMENTS} + depends_on: + - mysql + healthcheck: + test: ["CMD", "curl", "-f", "http://127.0.0.1"] + interval: 2s + timeout: 10s + retries: 30 + mysql: + image: 'mysql:8.0' + restart: unless-stopped + volumes: + - './docker/mysql:/var/lib/mysql' + environment: + - MYSQL_ROOT_PASSWORD=${SERVICE_PASSWORD_EASYAPPOINTMENTS} + - MYSQL_DATABASE=easyappointments + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1"] + interval: 5s + timeout: 20s + retries: 10 From 1138ec0dea197f980aa4266b9894b6202f84e9ba Mon Sep 17 00:00:00 2001 From: Luan Estradioto Date: Sun, 21 Jul 2024 13:30:28 -0300 Subject: [PATCH 017/863] add storage:link to dev environment --- app/Console/Commands/Dev.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/Console/Commands/Dev.php b/app/Console/Commands/Dev.php index 964b8e46e..20a2667c3 100644 --- a/app/Console/Commands/Dev.php +++ b/app/Console/Commands/Dev.php @@ -48,6 +48,13 @@ class Dev extends Command echo "Generating APP_KEY.\n"; Artisan::call('key:generate'); } + + // Generate STORAGE link if not exists + if (! file_exists(public_path('storage'))) { + echo "Generating STORAGE link.\n"; + Artisan::call('storage:link'); + } + // Seed database if it's empty $settings = InstanceSettings::find(0); if (! $settings) { From 6b178f8b2e646728203bf4a7a7135dad6621ba29 Mon Sep 17 00:00:00 2001 From: johann Date: Wed, 24 Jul 2024 16:09:50 +0200 Subject: [PATCH 018/863] added bookstack template --- templates/compose/bookstack.yaml | 59 ++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 templates/compose/bookstack.yaml diff --git a/templates/compose/bookstack.yaml b/templates/compose/bookstack.yaml new file mode 100644 index 000000000..f374314af --- /dev/null +++ b/templates/compose/bookstack.yaml @@ -0,0 +1,59 @@ +# documentation: https://www.bookstackapp.com/docs/ +# slogan: BookStack is a simple, self-hosted, easy-to-use platform for organising and storing information +# tags: free-and-open-source,mfa,dark-light-themes,searchable,connected,simple-interface,diagramms,notes +# port: 6875 + +services: + bookstack: + image: lscr.io/linuxserver/bookstack + container_name: bookstack + environment: + - PUID=1000 + - PGID=1000 + - TZ=Europe/Berlin + - APP_URL=$SERVICE_FQDN_BOOKSTACK + - DB_HOST=bookstack_db + - DB_PORT=3306 + - DB_USER=$SERVICE_USER_MYSQL + - DB_PASS=$SERVICE_PASSWORD_MYSQL + - DB_DATABASE=${MYSQL_DATABASE-bookstackapp} + - QUEUE_CONNECTION=$QUEUE_CONNECTION + volumes: + - 'bookstack_app_data:/config' + ports: + - '6875:80' + restart: unless-stopped + healthcheck: + test: + - CMD-SHELL + - 'wget -qO- http://127.0.0.1:80/' + interval: 5s + timeout: 20s + retries: 10 + depends_on: + bookstack_db: + condition: service_healthy + bookstack_db: + image: lscr.io/linuxserver/mariadb + container_name: bookstack_db + environment: + - PUID=1000 + - PGID=1000 + - TZ=Europe/Berlin + - MYSQL_ROOT_PASSWORD=${SERVICE_PASSWORD_MYSQLROOT} + - MYSQL_DATABASE=${MYSQL_DATABASE} + - MYSQL_USER=${SERVICE_USER_MYSQL} + - MYSQL_PASSWORD=${SERVICE_PASSWORD_MYSQL} + volumes: + - 'bookstack_db_data:/config' + restart: unless-stopped + healthcheck: + test: + - CMD + - mysqladmin + - ping + - '-h' + - 127.0.0.1 + interval: 5s + timeout: 20s + retries: 10 From 380f2f4029aea3a9dcb04111a8d6db657f767a39 Mon Sep 17 00:00:00 2001 From: Juan Felipe Date: Tue, 30 Jul 2024 18:17:38 -0300 Subject: [PATCH 019/863] feat: Add Mautic 4 and 5 to service templates --- public/svgs/mautic.svg | 17 +++++ templates/compose/mautic4.yaml | 46 ++++++++++++++ templates/compose/mautic5.yaml | 111 +++++++++++++++++++++++++++++++++ 3 files changed, 174 insertions(+) create mode 100644 public/svgs/mautic.svg create mode 100644 templates/compose/mautic4.yaml create mode 100644 templates/compose/mautic5.yaml diff --git a/public/svgs/mautic.svg b/public/svgs/mautic.svg new file mode 100644 index 000000000..b528f72ef --- /dev/null +++ b/public/svgs/mautic.svg @@ -0,0 +1,17 @@ + + + + + + + + + + diff --git a/templates/compose/mautic4.yaml b/templates/compose/mautic4.yaml new file mode 100644 index 000000000..f1e567453 --- /dev/null +++ b/templates/compose/mautic4.yaml @@ -0,0 +1,46 @@ +# documentation: https://www.mautic.org/ +# slogan: Mautic v4 Open Source Marketing Automation +# tags: php,mautic,marketing,automation,email,service,4,open,source,crm +# logo: svgs/mautic.svg +# port: 8880 + +services: + rabbitmq: + image: 'rabbitmq:3' + environment: + - 'RABBITMQ_DEFAULT_VHOST=${RABBITMQ_DEFAULT_VHOST:-mautic}' + volumes: + - 'rabbitmq-data:/var/lib/rabbitmq' + database: + image: powertic/percona-docker + environment: + MYSQL_ROOT_PASSWORD: ${SERVICE_PASSWORD_64_MYSQL} + volumes: + - database:/var/lib/mysql + command: --character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci --sql-mode="" + mautic: + image: mautic/mautic:v4-fpm + volumes: + - mautic_data:/var/www/html + environment: + - SERVICE_FQDN_MAUTIC_80 + - MAUTIC_DB_HOST=database + - MAUTIC_DB_USER=root + - MAUTIC_DB_PASSWORD=${SERVICE_PASSWORD_64_MYSQL} + - MAUTIC_DB_NAME=mautic4 + - MAUTIC_RUN_MIGRATIONS=true + - MAUTIC_RUN_CRON_JOBS=false + - MAUTIC_RABIITMQ_HOST=rabbitmq + - MAUTIC_RABIITMQ_PORT=5672 + - MAUTIC_RABIITMQ_USER=guest + - MAUTIC_RABIITMQ_PASSWORD=guest + - MAUTIC_RABIITMQ_VHOST=mautic + - MAUTIC_ADMIN_EMAIL=${MAUTIC_ADMIN_EMAIL} + - MAUTIC_ADMIN_PASSWORD=${SERVICE_PASSWORD_ADMIN} + - MAUTIC_ADMIN_FIRSTNAME=${MAUTIC_ADMIN_FIRSTNAME} + - MAUTIC_ADMIN_LASTNAME=${MAUTIC_ADMIN_LASTNAME} + healthcheck: + test: ["CMD", "curl", "-f", "http://127.0.0.1:80"] + interval: 2s + timeout: 10s + retries: 15 diff --git a/templates/compose/mautic5.yaml b/templates/compose/mautic5.yaml new file mode 100644 index 000000000..309a619d2 --- /dev/null +++ b/templates/compose/mautic5.yaml @@ -0,0 +1,111 @@ +# documentation: https://www.mautic.org/ +# slogan: Mautic v5 Open Source Marketing Automation +# tags: php,mautic,marketing,automation,email,service,5,open,source,crm +# logo: svgs/mautic.svg +# port: 8880 + +services: + db: + image: 'mysql:8.0' + environment: + - 'MYSQL_ROOT_PASSWORD=${SERVICE_PASSWORD_64_MYSQLROOT}' + - 'MYSQL_DATABASE=${MYSQL_DATABASE}' + - 'MYSQL_USER=${MYSQL_USER}' + - 'MYSQL_PASSWORD=${SERVICE_PASSWORD_64_MYSQL}' + volumes: + - 'mysql-data:/var/lib/mysql' + healthcheck: + test: 'mysqladmin --user=$$MYSQL_USER --password=$$SERVICE_PASSWORD_64_MYSQL ping' + start_period: 5s + interval: 5s + timeout: 5s + retries: 10 + rabbitmq: + image: 'rabbitmq:3' + environment: + - 'RABBITMQ_DEFAULT_VHOST=${RABBITMQ_DEFAULT_VHOST}' + volumes: + - 'rabbitmq-data:/var/lib/rabbitmq' + mautic_web: + image: 'mautic/mautic:latest' + ports: + - 8880:80 + volumes: + - './mautic/config:/var/www/html/config:z' + - './mautic/logs:/var/www/html/var/logs:z' + - './mautic/media/files:/var/www/html/docroot/media/files:z' + - './mautic/media/images:/var/www/html/docroot/media/images:z' + - './cron:/opt/mautic/cron:z' + environment: + - SERVICE_FQDN_MAUTIC_80 + - 'DOCKER_MAUTIC_LOAD_TEST_DATA=${MAUTIC_LOAD_TEST_DATA:-false}' + - 'DOCKER_MAUTIC_RUN_MIGRATIONS=${MAUTIC_RUN_MIGRATIONS:-false}' + - 'MAUTIC_DB_HOST=${MYSQL_HOST}' + - 'MAUTIC_DB_PORT=${MYSQL_PORT}' + - 'MAUTIC_DB_DATABASE=${MYSQL_DATABASE}' + - 'MAUTIC_DB_USER=${MYSQL_USER}' + - 'MAUTIC_DB_PASSWORD=${SERVICE_PASSWORD_64_MYSQL}' + - 'MAUTIC_MESSENGER_DSN_EMAIL=${MAUTIC_MESSENGER_DSN_EMAIL}' + - 'MAUTIC_MESSENGER_DSN_HIT=${MAUTIC_MESSENGER_DSN_HIT}' + healthcheck: + test: ["CMD", "curl", "-f", "http://127.0.0.1:80"] + interval: 2s + timeout: 10s + retries: 15 + depends_on: + db: + condition: service_healthy + mautic_cron: + image: 'mautic/mautic:latest' + links: + - 'db:mysql' + volumes: + - './mautic/config:/var/www/html/config:z' + - './mautic/logs:/var/www/html/var/logs:z' + - './mautic/media/files:/var/www/html/docroot/media/files:z' + - './mautic/media/images:/var/www/html/docroot/media/images:z' + - './cron:/opt/mautic/cron:z' + environment: + - DOCKER_MAUTIC_ROLE=mautic_cron + - 'MAUTIC_DB_HOST=${MYSQL_HOST}' + - 'MAUTIC_DB_PORT=${MYSQL_PORT}' + - 'MAUTIC_DB_DATABASE=${MYSQL_DATABASE}' + - 'MAUTIC_DB_USER=${MYSQL_USER}' + - 'MAUTIC_DB_PASSWORD=${SERVICE_PASSWORD_64_MYSQL}' + - 'MAUTIC_MESSENGER_DSN_EMAIL=${MAUTIC_MESSENGER_DSN_EMAIL}' + - 'MAUTIC_MESSENGER_DSN_HIT=${MAUTIC_MESSENGER_DSN_HIT}' + depends_on: + mautic_web: + condition: service_healthy + healthcheck: + test: ["CMD", "curl", "-f", "http://127.0.0.1:80"] + interval: 2s + timeout: 10s + retries: 15 + mautic_worker: + image: 'mautic/mautic:latest' + links: + - 'db:mysql' + volumes: + - './mautic/config:/var/www/html/config:z' + - './mautic/logs:/var/www/html/var/logs:z' + - './mautic/media/files:/var/www/html/docroot/media/files:z' + - './mautic/media/images:/var/www/html/docroot/media/images:z' + - './cron:/opt/mautic/cron:z' + environment: + - DOCKER_MAUTIC_ROLE=mautic_worker + - 'MAUTIC_DB_HOST=${MYSQL_HOST}' + - 'MAUTIC_DB_PORT=${MYSQL_PORT}' + - 'MAUTIC_DB_DATABASE=${MYSQL_DATABASE}' + - 'MAUTIC_DB_USER=${MYSQL_USER}' + - 'MAUTIC_DB_PASSWORD=${SERVICE_PASSWORD_64_MYSQL}' + - 'MAUTIC_MESSENGER_DSN_EMAIL=${MAUTIC_MESSENGER_DSN_EMAIL}' + - 'MAUTIC_MESSENGER_DSN_HIT=${MAUTIC_MESSENGER_DSN_HIT}' + depends_on: + mautic_web: + condition: service_health + healthcheck: + test: ["CMD", "curl", "-f", "http://127.0.0.1:80"] + interval: 2s + timeout: 10s + retries: 15 From 18ae29ba99d61b8275776c9d975ddb39092c9144 Mon Sep 17 00:00:00 2001 From: Alex Renoki Date: Wed, 31 Jul 2024 07:11:08 +0300 Subject: [PATCH 020/863] Added langfuse --- public/svgs/langfuse.png | Bin 0 -> 9788 bytes templates/compose/langfuse.yaml | 46 ++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 public/svgs/langfuse.png create mode 100644 templates/compose/langfuse.yaml diff --git a/public/svgs/langfuse.png b/public/svgs/langfuse.png new file mode 100644 index 0000000000000000000000000000000000000000..8dec0fe4ae1dd9c91ea9e8e0d6ed89227fef4143 GIT binary patch literal 9788 zcmd_wAZW3k3)?E008jSRF(8z`rrR+SQsz0+N35A0ANQ`Q<67; z@IC#hYV4cQOJVjW z=+2CTZLHv@3x3hp2Vr z-53A{fC-BAf5EkWGC{Z~IR~wS-b_spN7U%U<0LkTXagX4-OYgU1$tb- z16jB35xt=ZhbU;t7?5N3KRITLU()PUU)H{XuWN!E5CO3ERm`gI@iI>YLC@&m z+P#l=WRJ>>eM&KYT~u{Dq;pFh*z0S6V_a1pO)5AFNMbjVB3$A##fYVRjee4S$@{W3+^?4$Yz6pafw`BEI^P23RoW1HhRA$`Z771WZ6u5&SI!bVYLX zSta>!1tRnf!rv&$IjHw#G17bk-tZobp#g~@dFjglN|Ts7vLM-*)sjkn0^vtjROItd zLXJ>&xooh|%v6K?g$bqhQb2}D&RA{V*ON8yb+y|Gi*wEy9bg34Ti2(!7Ux5agS+g) zYL9Moh&HuE{H*8bq$r+In>d{k=KuwKz`QvQ&OgJ0r(QqWT)*gzY;@f8T5>%(f@npCbxIjY{QPjA&4ywS%-jr&|(B0`;Vd(k>k|j3So`zx85v3bG+|r&){On%mDok1P8jHl3TSS0b0H`5mw-O!s)0j3C zyN5I_tpm>C?Ji)qPi=?r9sla`*WPCI;Zr^lrebww&>p9FNGieAao0P%Wyugznh8|c z2zUHKR>Ti3Ze+`ukejjIN*|=*9cP%_PU+Xlcqz=qR6J>cjb+01gHS0r#~c8+Axv0* z8mVN+Ht4XCAW9I?Srg+yL+$>hmxe>5V4{O)P>?bL^6^%_oHqWq+OJ`XKefstp_Es_ zvQe40jSVHSL=Qh3fnSVM|I4WOOj?tuWz7Ukjwjc1`q2kEK&2Y8Kq-s3rgkN=j7O2# zeZ_VNpDL%bSHXLzgwl#C3(f7tUN(oKdtE|io0q%~1gVCesqX$wMEE%RD04D|{Eqqs zgr@CV*h)#@bu$8fk%S(*L58Sb(@0Pl8*OS#A$dY|R(V_wrIg-vp?v6eI5`#uQ~|+8 z-&;Zi4S)l2A&`*tK`5-gkxYeOpxjygG+zl7mxj7-dTW3=bdcq4Kf54KihTyb4OCa= zWj+tYQR32TkHFRUAq_f-66MNquL#K=R(E%LgAna?c~H3b_L{Vb%)9g3oBjn%Z1geU z)~sm>zo)Rx?SmRj^z@&8`zhq#Qe12dfr!l$ysLHV-qsp(P>l*Lo3zVG*bB)nFu2P8 z?apCXR1i0o(MN|MAA}fg)2q%o<V|GNqUIHr;jn6hW7pC+OPWg0TI{71@Z~_K?ENI5| zyJR-0q(G_06pF8J&;NmdfhY!ak6>*vanO6G@}_BG3#56Y4EU>W(zt*EIKb3#K7D6I zVyTCGOv}W^zUCFPVUf*f7v4d^X`zKV)4G$2cL%QDGzo~I6DK2c%HFx|{x&jrL_=Mm zI2}T#8;fd_;kKGtA9A$#mn4D5AVGw!jGB>Z*(|F4P&>GVcQ+>Uyl?upAadE;3HLDv4i=^07zQV zj>$%;WLQXgjG?-*N8!Dyx(29)HE8EevL%7Fj6hj#UcTw*IAMBKR^9UeZsd zKUmAULllR;H#om|N33fD<8jek{WLT`KT$fI(|5Hlt>Rty4szg7s4#Ce1}dTPzgPBR>LKCm;Eh)%{okTklV!w_vmbww4VlroHO(<2WU5-m%|)QqZa7qADqSPc|)zuP;K57F~=oLaEF`)nVt%k6=So2EfS0* zc)f(Rfy+UlYd9*u!?;qII&smWGpx@=Ldq!6=e zRi0b?W!~B!*Y&cC#zngCNn)T?3E3bUeXQWd%x2ek@(K6mUnx(S3!_6c;RtD?MX?&^ zPlKOcJMC2u6~tu@DHG4JGQ`1IP7k%$kImCp#VrlN8m6z`YY^9yv!F8nK*W~Z#;sRyPmyhc8GTqb} zqEDEA)zX*o^&M=}+HQ6eA=F>rJ?U8M2`(8O|E~4*g@AP%e zrtl7){dwg+;XA|G4*uMgV-TplkeHBlv^jT5oywy|AQj zKXC8CgiQE+uXAy??Z#G-#mIM%ruY*X^z~x}$DI8n1dT-deG>5>e;=Miu7oH3K=PcFM%){0hRUr`tO^CFSX)vb`wSQLXCN4g{$#GP( z;U{)xq31T&G%PIY7DsWCm_SssmN%UzLQL^b!(2-{c>}vuv};gqJ=6g1HMow0@ozdP z{pyN8{jg)UOBpLLqc(5{-&6#=V9>E$E0j|_{+>WXbEUheMtq;>rB#sPYk`ay4_4a@RfWP4f@(z@4xc+}la2J{%;v#1x1jYmE0$L|4 zDPh>^_46X9Ct*>>Je9)Y2BE(T$#HDjROY{km;UYQ5G}w#L%TX{2)^xTlW=xVNx3a{ z#)9Iy@tXW|5gTuAv3|NvD2S76Aml{{yBY~jngYJ2f0EN9BChndV+|q2r!(yQVELg1 zVH@>v1AV#|_j}Y1fxAYNBp16DuADU00C>-LKw5F=`h7uct;X@) zc+JF|mn)P&2TO%ReGh75H%$QF4m}cgp?PlNsd8EK-%PAfgpF9yNG3dMU5$CuxeDU*UhhC#k>kW^L4EAbjxa&>8yYYQ~Ob59hMX8bxHDfdSo@ z3RFjJpY(o^MO_?ImH@hN*K-Vnz;>W6n47Xc&6wOc_sNKg_}hp z_5u>(o+UbG_4;%@KA_mU#Z8#h>=XvP$8718TQNO?|61CUpiwYCOixB+7bf8!Va(_e zhS|6twh{_f*^y`DH>dE1Jn0-i5fTR;erD7ouuWx$Tb}a{lD?9QVON|t%ykPZ>!|un zeGnue)~#gSbk?*gGKEE5i{`SBUd2DI`GWve2z^X}OdKc4GrS4FN3k&V3v1n@_hERC z&qT6w!RvPJm9B0(s{()yD4{k^TX|%%I{N-2OR0+b)L{dxLQ#sXVwPCAHG9SFEaj4m zUggUrB7|8pI9ByhK#GvPht$rfFUKJak@A6YqKb^I?-;eN=-cih=crKgY^3I%M}Nl0 z&&IHKP`&zh6_&Bbn!CrJ|Z_P%oL0EUXd2JT4)Ai=`;4}$qFpJQGKs| z+F=S#C`iY*Wp=_2vRA@C^{;zNM$%^dKu_#w{sWcjb#g!gQ4|z2#w`B!RY59Vn9LI} zaX3lG4=WYU_hP2nr6NH7zi4mNM75=#(?)D8MK*Bbn-S?GqP@}f9e4@9; zG^E=_p|nMp9N$=Ko_{|_;4yd~ol>4~3J!XOww=Ruo!sr96eMHW z1GHQ=IIPk-U^H(*J95MXuO<_Aw4%Oj;$QimyoK>hS>Br)G$vfuM_^Tu1#;%vSS^S) z=}x|!iuf=ycaump!?NlE|268@Z&4?;kEn_>g$#V`3!jwGZECqC@7>&Dz-M7MOCmAV zYR>rdlqZ%OJ6f1}$p?y|ouQ-hfhq7!4%YuoUrpypns2BP*2y9Ka%R^V4NS#a3-l&b zAJEtgFf~JIj7;AS5?Iiy`P;#c2T~Ow{tccSse=)(6>$dC zFz)+|%Ay(k@2IqreAC6PhSGcz24&OIB5?&EWrDs8e6Vq%?-EA$6O`p;4$vOn&Cz=e zPaL$oWn6mfuhmOo zoQW4&CpeJga*GMYViH!fB5f+_2!boC3A^@uHBD{Y&LX-ZW(V>;!0SV=PG!L6iyy`={8 zgCoa$@AGxu(xZ9xPwBi3Kvnu9m7i_84RLuo{+<8wZ{op^0+Q~Ygnvw|dfN}yok7sI zw-^li!CAZyY^reFNnTmo6a_7rGjp-_-KEWU`=c3YekC}QgM?-ecYp`_{U zw3245Yn0W{B;6HjHhdq)bHh86g&myJE(z0W-*AQyU$xmoKF;$vCuyF1%TpWE4+s4v zo~U}hHxr3=8-Q}0upuTJ7EanAtTvlZN+H)gZ&D2u^UvNmY-uYX9(N(QiSb0^i6Nxk zq>biS=o%GVf?Ne@;aW8@<(LP5Bf7-4Mg&Up$bYx`p?dLv5c#1^XFXS8y|Kq9fDDXv z>Jyy<4y``?k`k)5n92dWhM7j>E`-~%{&4w8+6=va8inW{0F=@SM221Vn}*(?Z$SUC zH2wFYg=oWZABjTXJlwfMY3x}A+MqXy9@juSd+yLd`D_@V_=EM&;!K}v@1zN{fBc)5NfbG}1dnfr;B7|017J|SQ*9tGd9AHe?& z8^NHe@_;)E#kkF1h*;Wm(uG-ZKKL{#~a&{7{%y>E&?1GS0lMq5elHh%Q3-ryvb?V=rIW<^Y)G-v3G;A^vM(ynJp(!%`a zx~$o*`3Ul+_-4IvBEy{(U$C$$3}7_Jj9+=_T$H|_oq;-IC^q+($pSGcT_Vrmn)wh7z=F@1$4FSV}y01cFHh6}H zIplHH>07?L+Ips+=!bW|P;PPtin0;e+1ulWr4od7?qKJY!O**3d(yF>K5c1Fip=O! zy8ZZ>+mEmbyrEV7!^k0D`yUn-bOxd~E^$Z5g1(nv|D8Z)B6c-6I>ZL2hbej(jpc_UHNPpb3iQzZ z{>l&YBEq<4odjFbI6T9_J9kF<`7OJa=-3At`_6SSVlFvZG0Qp9eehv-a z8#2+%vDNs{tT8FEXt9&PY=zUm+DNt&^PKYZxIc`e zIjX;+z<*g2V{X0$+^H-CQ5-XfA;=l_% znXR#m633e_d49zF>?KlU_jyXFZVS29)U1qXLuZ$BpN>5F=%M6mFKh1BpNlt2XcrFS zIKzzYh!&*E_yP>rcwCgTb*L;kFzK$Prj~%{xiAl&r?HB-)ysw-uSS2CL2`>^(_&6! zuv<3rbT}@kdR{RYpbbxQPO30qUM41xA3dlSg0HGJl+{GpMo35+P9@unODK zn)8L_7r*fr@_<2+B|+^ghyCTLnAQ^Jmft!LY(V!in(UEfRNswBe^4<^sasO&(FM>h z??@NmyTqWjwDHlaW|T4E)aovfC%{k4%sa`o1Cu6-KP%6M7DviHD#9d_Z}En)k^Y9{ z31>Vi)bAaa=s)HQSEmH^%pA~ha!5r)MC($sf{+N_5-km(!5VUoML=ZyXVNsdd) zTphgK5IfpTvrwyYvr{_3DuGfg+PwbEPa{2PMDmrt1oB&?{%`Z`*=F=R>OO@lM&$*b zX(hB;mF!Km>0Y5q82i8?%L|>+UEiMx@zl}>WxuGQ`2^STdIoq-I`jtWcG}8dKNOAR z1L2k7et91BCgg4A8Lh1xvNALGanKReF<_@?GPCLQqCA{U*uI&?Bn^38!G-(%nNzj- z4Z*Pn>kZCO=h4GPT2|C#g4DNKzQYk6xQgwm_B3fP^RE*^Kn|vL^mRjn2!2a?dXwar zzb73gQsWMnMgAkhWpHM_jhUZT1jdFBMbHk1A(j^);-uHkfGmpmIA!MYX_sdL9?NhG z2y#jOlJ5{^IVf!oAU2vWGrp@vU-R1>vqm(qB*n`6Goh2*W$%cc zC~xjF^!jeaJG)Eqo28*MH%J&s5{x@JC>5F0uDBW7u+L{sVY$|F44oUMfu;q7gyh=& z<`_>en(B zoZ(GZoc#<>7|RwXK7_MT%0}nPgBM?vC=>`t|Deak6-w6?fD8;ze{Fw+6jqSfzl{}h z!}hZ7e6nZ#zML_Nxjf=d^M&!L->~3b9P(uiZGF&NCJ%rNNV?;AWS|%4<*9O8k0&Gp zHK}p1Q}{XT{56LtZ1GS;Ni{B*UPPK$`dEG%@-!UCCEuo+)EKLFo|_lr`{cZdsMSx5 zHha;w9nKJ6mhtiHM94;9kdlh+eIU+sh493*4j{qTgT$D$x9@;KXqv(>pi4vcWxJk0 z$-qq7NaWzEYB||>H7zZ$bRd*;+ri@L{%|o9f2zs4{ZTsph?C;Lg0g{N<|73K6Ibk3 zO^}$KD}-_m|Asoh<*CO{i7*fVR-=>%E>j)xwZt4cA(~TJ<>=2AB>+4lglJ|~p1iLV z{ggjcKuS{1VYZK_#WQlQvLz6Z&DpF=rv)o->So&xMMriDD6aR`fpa@WwOH94Vj2Y1ZD`NE9Jb;Kw}d1I zp7sn)MqD*sXAvEufeC_s_(ASoG1Kf?>kc6J!&RA$%Q)n`J$_+;bHFFk%&P4X;jgZxZE*{A5 z#af=ez$91y$TR}G(*ghZN>A9xBs7hPJC$|fBehX(QUta@hGFaKy0S%Ws^Ndv+aPm| z$m}_z!{3LZ8Ldd+jRQ^TqR0%*_DOSCej#2S(B(|w_=XYPl3BAFWF_*k+6?#w@$<0H zi=;B$=nx#<+dfdN}bx7*~OSh zmX8jO;keI;LgQ*AgjE3Lj z%Be8)%+N?GF)mEZ<82SXC!|^;sMTIzn&wlsM$cyz7^c`AIiF}a;*njjaA|kX2~|zd zpmErW9QvmqnTWO)k>SMZ@dllIscG8%W-&3HCx##HG87vEHeF?-#goUgEP^7(DZ{xN ziJVf!u}-!u0tQkKBD=T}$wHMfh6fhV-t)5zR19!tMb}ph8{@vDbH3ukyg_KHeazZ+ z+x!7+eqBQ9)skOxT-=*VTww>2Nh(6V`npM(@U$w@+k`?zFk4^` zfvVPHHamfKlLc`nXd8))?5I=9(8^^8{|>`9vqA-n2VtJ)MoHls0{!TDhtV~G;4%je z36gkj->^8qTx1*H36{JF8FDcu;)$7vzfXyLAqC(sL|8B7Jo$(k^aCLEeP|W>IyH)S z`}lJhgvPhsT+HFFNUozU??Z*dM|%K>q}xQ$eCbvBoOfrLN0$QZlko-Rd6Deo8v18} z{;;T0tOIl)?{b_s5FBunOPY}iTPCi|3%q&Mg;(#pBHkjZi|vh(q3ML0o0V= KDb*-ghx{KZU0w?S literal 0 HcmV?d00001 diff --git a/templates/compose/langfuse.yaml b/templates/compose/langfuse.yaml new file mode 100644 index 000000000..1512b0f07 --- /dev/null +++ b/templates/compose/langfuse.yaml @@ -0,0 +1,46 @@ +# documentation: https://langfuse.com/docs +# slogan: Langfuse is an open-source LLM engineering platform that helps teams collaboratively debug, analyze, and iterate on their LLM applications. +# tags: ai, qdrant, weaviate, langchain, openai, gpt, llm, lmops, langfuse, llmops +# logo: svgs/langfuse.png +# port: 3000 + +version: "3" + +services: + langfuse: + image: langfuse/langfuse + restart: always + environment: + - DATABASE_URL=postgresql://${SERVICE_USER_POSTGRES}:${SERVICE_PASSWORD_POSTGRES}@postgres:5432/${POSTGRES_DB:-langfuse} + - NEXTAUTH_URL=$SERVICE_FQDN_LANGFUSE_3000 + - NEXTAUTH_SECRET=$NEXTAUTH_SECRET + - SALT=$SERVICE_PASSWORD_SALT + - AUTH_DISABLE_SIGNUP=${AUTH_DISABLE_SIGNUP:-false} + - TELEMETRY_ENABLED=${TELEMETRY_ENABLED:-false} + - LANGFUSE_ENABLE_EXPERIMENTAL_FEATURES=${LANGFUSE_ENABLE_EXPERIMENTAL_FEATURES:-false} + entrypoint: + - node + - web/server.js + healthcheck: + test: ["CMD", "curl", "-f", "http://127.0.0.1:3000/api/public/health"] + interval: 5s + timeout: 5s + retries: 3 + depends_on: + postgres: + condition: service_healthy + postgres: + image: "postgres:16-alpine" + environment: + - POSTGRES_DB=${POSTGRES_DB:-langfuse} + - POSTGRES_PASSWORD=$SERVICE_PASSWORD_POSTGRES + - POSTGRES_USER=$SERVICE_USER_POSTGRES + volumes: + - "pg-data:/var/lib/postgresql/data" + healthcheck: + test: + - CMD-SHELL + - "pg_isready -h localhost -U ${POSTGRES_USER} -d ${POSTGRES_DB}" + interval: 5s + timeout: 5s + retries: 10 From 22a58eea8fcf642b5c8d551b1b7a274de85c8194 Mon Sep 17 00:00:00 2001 From: Telokis <6382729+Telokis@users.noreply.github.com> Date: Tue, 6 Aug 2024 21:44:11 +0200 Subject: [PATCH 021/863] Add Organizr --- public/svgs/organizr.png | Bin 0 -> 13884 bytes templates/compose/organizr.yaml | 20 ++++++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 public/svgs/organizr.png create mode 100644 templates/compose/organizr.yaml diff --git a/public/svgs/organizr.png b/public/svgs/organizr.png new file mode 100644 index 0000000000000000000000000000000000000000..92541ea72a2d618694839c857e00da415ace706d GIT binary patch literal 13884 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 S0->kEV1P0z(zTMNq5lKhnC{d7 literal 0 HcmV?d00001 diff --git a/templates/compose/organizr.yaml b/templates/compose/organizr.yaml new file mode 100644 index 000000000..badbd14ae --- /dev/null +++ b/templates/compose/organizr.yaml @@ -0,0 +1,20 @@ +# documentation: https://docs.organizr.app/ +# slogan: Homelab Services Organizer +# tags: tool +# logo: svgs/organizer.png +# port: 80 + +services: + organizr: + image: organizr/organizr:latest + restart: unless-stopped + environment: + - SERVICE_FQDN_ORGANIZR_80 + - branch=v2-master + volumes: + - organizr-data:/config + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:80"] + interval: 2s + timeout: 10s + retries: 30 From a2199429878a380e30021d1a10d7ca80acf18107 Mon Sep 17 00:00:00 2001 From: Telokis <6382729+Telokis@users.noreply.github.com> Date: Tue, 6 Aug 2024 21:44:34 +0200 Subject: [PATCH 022/863] Fix icon path --- templates/compose/organizr.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/compose/organizr.yaml b/templates/compose/organizr.yaml index badbd14ae..df95730c4 100644 --- a/templates/compose/organizr.yaml +++ b/templates/compose/organizr.yaml @@ -1,7 +1,7 @@ # documentation: https://docs.organizr.app/ # slogan: Homelab Services Organizer # tags: tool -# logo: svgs/organizer.png +# logo: svgs/organizr.png # port: 80 services: From df796dffa2598354b7edcf3965dd00d45787eebf Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Thu, 8 Aug 2024 01:02:48 +0200 Subject: [PATCH 023/863] fix delte networks and unused images of services when deleted --- app/Actions/Service/DeleteService.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/Actions/Service/DeleteService.php b/app/Actions/Service/DeleteService.php index 194cf4db9..b043082ac 100644 --- a/app/Actions/Service/DeleteService.php +++ b/app/Actions/Service/DeleteService.php @@ -3,6 +3,7 @@ namespace App\Actions\Service; use App\Models\Service; +use App\Actions\Server\CleanupDocker; use Lorisleiva\Actions\Concerns\AsAction; class DeleteService @@ -33,6 +34,11 @@ class DeleteService foreach ($storagesToDelete as $storage) { $commands[] = "docker volume rm -f $storage->name"; } + + $uuid = $service->uuid; + instant_remote_process(["docker network disconnect {$uuid} coolify-proxy"], $server, false); + instant_remote_process(["docker network rm {$uuid}"], $server, false); + $commands[] = "docker rm -f $service->uuid"; instant_remote_process($commands, $server, false); @@ -50,6 +56,9 @@ class DeleteService $task->delete(); } $service->tags()->detach(); + $service->forceDelete(); + + CleanupDocker::run($server, true); } } } From 070daee28e8f5c91401c37c778b919f1270042a0 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Thu, 8 Aug 2024 01:19:17 +0200 Subject: [PATCH 024/863] remove networks and cleanup unused images when stoping dockercompose build pack containers --- app/Actions/Application/StopApplication.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/Actions/Application/StopApplication.php b/app/Actions/Application/StopApplication.php index 1f05e29ac..70575c821 100644 --- a/app/Actions/Application/StopApplication.php +++ b/app/Actions/Application/StopApplication.php @@ -3,6 +3,7 @@ namespace App\Actions\Application; use App\Models\Application; +use App\Actions\Server\CleanupDocker; use Lorisleiva\Actions\Concerns\AsAction; class StopApplication @@ -13,7 +14,6 @@ class StopApplication { if ($application->destination->server->isSwarm()) { instant_remote_process(["docker stack rm {$application->uuid}"], $application->destination->server); - return; } @@ -23,7 +23,7 @@ class StopApplication $servers->push($server); }); foreach ($servers as $server) { - if (! $server->isFunctional()) { + if (!$server->isFunctional()) { return 'Server is not functional'; } if ($previewDeployments) { @@ -44,10 +44,11 @@ class StopApplication } } if ($application->build_pack === 'dockercompose') { - // remove network $uuid = $application->uuid; instant_remote_process(["docker network disconnect {$uuid} coolify-proxy"], $server, false); instant_remote_process(["docker network rm {$uuid}"], $server, false); + + CleanupDocker::run($server, true); } } } From 4d0acee95cf32173411523429598bb21774e1ca8 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Thu, 8 Aug 2024 12:31:37 +0200 Subject: [PATCH 025/863] UI options for deletion WIP --- app/Actions/Service/DeleteService.php | 4 +-- app/Jobs/DeleteResourceJob.php | 31 +++++++++++++++---- .../livewire/project/shared/danger.blade.php | 4 ++- 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/app/Actions/Service/DeleteService.php b/app/Actions/Service/DeleteService.php index b043082ac..7c8eaf75d 100644 --- a/app/Actions/Service/DeleteService.php +++ b/app/Actions/Service/DeleteService.php @@ -10,7 +10,7 @@ class DeleteService { use AsAction; - public function handle(Service $service) + public function handle(Service $service, bool $deleteConfigurations, bool $deleteVolumes, bool $deleteImages, bool $deleteNetworks) { try { $server = data_get($service, 'server'); @@ -61,4 +61,4 @@ class DeleteService CleanupDocker::run($server, true); } } -} +} \ No newline at end of file diff --git a/app/Jobs/DeleteResourceJob.php b/app/Jobs/DeleteResourceJob.php index dbf44dd5d..36f673986 100644 --- a/app/Jobs/DeleteResourceJob.php +++ b/app/Jobs/DeleteResourceJob.php @@ -6,6 +6,7 @@ use App\Actions\Application\StopApplication; use App\Actions\Database\StopDatabase; use App\Actions\Service\DeleteService; use App\Actions\Service\StopService; +use App\Actions\Server\CleanupDocker; use App\Models\Application; use App\Models\Service; use App\Models\StandaloneClickhouse; @@ -31,7 +32,11 @@ class DeleteResourceJob implements ShouldBeEncrypted, ShouldQueue public function __construct( public Application|Service|StandalonePostgresql|StandaloneRedis|StandaloneMongodb|StandaloneMysql|StandaloneMariadb|StandaloneKeydb|StandaloneDragonfly|StandaloneClickhouse $resource, public bool $deleteConfigurations = false, - public bool $deleteVolumes = false) {} + public bool $deleteVolumes = false, + public bool $deleteImages = false, + public bool $deleteNetworks = false + ) { + } public function handle() { @@ -59,19 +64,33 @@ class DeleteResourceJob implements ShouldBeEncrypted, ShouldQueue break; } - if ($this->deleteVolumes && $this->resource->type() !== 'service') { - $this->resource?->delete_volumes($persistentStorages); - } if ($this->deleteConfigurations) { $this->resource?->delete_configurations(); } + + if ($this->deleteVolumes && $this->resource->type() !== 'service') { + $this->resource?->delete_volumes($persistentStorages); + } + + if ($this->deleteImages) { + // Logic to delete images + } + + if ($this->deleteNetworks) { + // Logic to delete networks + } + + $server = data_get($this->resource, 'server'); + if ($server) { + CleanupDocker::run($server, true); + } } catch (\Throwable $e) { ray($e->getMessage()); - send_internal_notification('ContainerStoppingJob failed with: '.$e->getMessage()); + send_internal_notification('ContainerStoppingJob failed with: ' . $e->getMessage()); throw $e; } finally { $this->resource->forceDelete(); Artisan::queue('cleanup:stucked-resources'); } } -} +} \ No newline at end of file diff --git a/resources/views/livewire/project/shared/danger.blade.php b/resources/views/livewire/project/shared/danger.blade.php index 276061a8e..20bd7310b 100644 --- a/resources/views/livewire/project/shared/danger.blade.php +++ b/resources/views/livewire/project/shared/danger.blade.php @@ -12,5 +12,7 @@ + + - + \ No newline at end of file From 319457020c41a4ffbe5c618927a1f2fea2cb268a Mon Sep 17 00:00:00 2001 From: nekomi2 Date: Thu, 8 Aug 2024 21:31:33 +0700 Subject: [PATCH 026/863] add joplin compose --- public/svgs/joplin.png | Bin 0 -> 5443 bytes templates/compose/joplin.yaml | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 public/svgs/joplin.png create mode 100644 templates/compose/joplin.yaml diff --git a/public/svgs/joplin.png b/public/svgs/joplin.png new file mode 100644 index 0000000000000000000000000000000000000000..d17a1d2c170d22bbe2c54b05689c6e700ea723a7 GIT binary patch literal 5443 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 Date: Fri, 9 Aug 2024 00:30:11 +0200 Subject: [PATCH 027/863] add logic --- app/Actions/Application/StopApplication.php | 3 +- app/Actions/Service/DeleteService.php | 34 +++++++--- app/Jobs/DeleteResourceJob.php | 28 ++++---- app/Livewire/Project/Shared/Danger.php | 12 +++- app/Models/Application.php | 68 +++++++++++-------- app/Models/ServiceApplication.php | 4 +- .../livewire/project/shared/danger.blade.php | 9 ++- 7 files changed, 94 insertions(+), 64 deletions(-) diff --git a/app/Actions/Application/StopApplication.php b/app/Actions/Application/StopApplication.php index c81e90518..73abeba7a 100644 --- a/app/Actions/Application/StopApplication.php +++ b/app/Actions/Application/StopApplication.php @@ -43,8 +43,7 @@ class StopApplication } if ($application->build_pack === 'dockercompose') { $uuid = $application->uuid; - instant_remote_process(["docker network disconnect {$uuid} coolify-proxy"], $server, false); - instant_remote_process(["docker network rm {$uuid}"], $server, false); + $application->delete_connected_networks($uuid); CleanupDocker::run($server, true); } diff --git a/app/Actions/Service/DeleteService.php b/app/Actions/Service/DeleteService.php index 7c8eaf75d..f32a44262 100644 --- a/app/Actions/Service/DeleteService.php +++ b/app/Actions/Service/DeleteService.php @@ -10,14 +10,16 @@ class DeleteService { use AsAction; - public function handle(Service $service, bool $deleteConfigurations, bool $deleteVolumes, bool $deleteImages, bool $deleteNetworks) + public function handle(Service $service, bool $deleteConfigurations, bool $deleteVolumes, bool $deleteImages, bool $deleteConnectedNetworks) { try { $server = data_get($service, 'server'); + if ($server->isFunctional()) { $storagesToDelete = collect([]); $service->environment_variables()->delete(); + $commands = []; foreach ($service->applications()->get() as $application) { $storages = $application->persistentStorages()->get(); @@ -31,21 +33,34 @@ class DeleteService $storagesToDelete->push($storage); } } - foreach ($storagesToDelete as $storage) { - $commands[] = "docker volume rm -f $storage->name"; + + // Delete volumes if the flag is set + if ($deleteVolumes) { + foreach ($service->applications()->get() as $application) { + $persistentStorages = $application->persistentStorages()->get(); + $application->delete_volumes($persistentStorages); + } } - $uuid = $service->uuid; - instant_remote_process(["docker network disconnect {$uuid} coolify-proxy"], $server, false); - instant_remote_process(["docker network rm {$uuid}"], $server, false); + // Delete networks if the flag is set + if ($deleteConnectedNetworks) { + $uuid = $service->uuid; + $service->delete_connected_networks($uuid); + } + // Command to remove the service itself $commands[] = "docker rm -f $service->uuid"; + // Execute all commands instant_remote_process($commands, $server, false); } } catch (\Exception $e) { throw new \Exception($e->getMessage()); } finally { + // Delete configurations if the flag is set + if ($deleteConfigurations) { + $service->delete_configurations(); + } foreach ($service->applications()->get() as $application) { $application->forceDelete(); } @@ -58,7 +73,10 @@ class DeleteService $service->tags()->detach(); $service->forceDelete(); - CleanupDocker::run($server, true); + // Run cleanup if images need to be deleted + if ($deleteImages) { + CleanupDocker::run($server, true); + } } } -} \ No newline at end of file +} diff --git a/app/Jobs/DeleteResourceJob.php b/app/Jobs/DeleteResourceJob.php index 36f673986..68036ee4a 100644 --- a/app/Jobs/DeleteResourceJob.php +++ b/app/Jobs/DeleteResourceJob.php @@ -31,10 +31,10 @@ class DeleteResourceJob implements ShouldBeEncrypted, ShouldQueue public function __construct( public Application|Service|StandalonePostgresql|StandaloneRedis|StandaloneMongodb|StandaloneMysql|StandaloneMariadb|StandaloneKeydb|StandaloneDragonfly|StandaloneClickhouse $resource, - public bool $deleteConfigurations = false, - public bool $deleteVolumes = false, - public bool $deleteImages = false, - public bool $deleteNetworks = false + public bool $deleteConfigurations, + public bool $deleteVolumes, + public bool $deleteImages, + public bool $deleteConnectedNetworks ) { } @@ -60,7 +60,7 @@ class DeleteResourceJob implements ShouldBeEncrypted, ShouldQueue break; case 'service': StopService::run($this->resource); - DeleteService::run($this->resource); + DeleteService::run($this->resource, $this->deleteConfigurations, $this->deleteVolumes, $this->deleteImages, $this->deleteConnectedNetworks); break; } @@ -72,20 +72,16 @@ class DeleteResourceJob implements ShouldBeEncrypted, ShouldQueue $this->resource?->delete_volumes($persistentStorages); } - if ($this->deleteImages) { - // Logic to delete images - } - - if ($this->deleteNetworks) { - // Logic to delete networks - } - $server = data_get($this->resource, 'server'); - if ($server) { + if ($this->deleteImages && $server) { CleanupDocker::run($server, true); } + + if ($this->deleteConnectedNetworks) { + $uuid = $this->resource->uuid; // Get the UUID from the resource + $this->resource?->delete_connected_networks($uuid); // Pass the UUID to the method + } } catch (\Throwable $e) { - ray($e->getMessage()); send_internal_notification('ContainerStoppingJob failed with: ' . $e->getMessage()); throw $e; } finally { @@ -93,4 +89,4 @@ class DeleteResourceJob implements ShouldBeEncrypted, ShouldQueue Artisan::queue('cleanup:stucked-resources'); } } -} \ No newline at end of file +} diff --git a/app/Livewire/Project/Shared/Danger.php b/app/Livewire/Project/Shared/Danger.php index 5f0178be4..cff1d453a 100644 --- a/app/Livewire/Project/Shared/Danger.php +++ b/app/Livewire/Project/Shared/Danger.php @@ -18,6 +18,10 @@ class Danger extends Component public bool $delete_volumes = true; + public bool $delete_images = true; + + public bool $delete_connected_networks = true; + public ?string $modalId = null; public function mount() @@ -33,7 +37,13 @@ class Danger extends Component try { // $this->authorize('delete', $this->resource); $this->resource->delete(); - DeleteResourceJob::dispatch($this->resource, $this->delete_configurations, $this->delete_volumes); + DeleteResourceJob::dispatch( + $this->resource, + $this->delete_configurations, + $this->delete_volumes, + $this->delete_images, + $this->delete_connected_networks + ); return redirect()->route('project.resource.index', [ 'project_uuid' => $this->projectUuid, diff --git a/app/Models/Application.php b/app/Models/Application.php index e2871da4b..324713bbf 100644 --- a/app/Models/Application.php +++ b/app/Models/Application.php @@ -152,7 +152,7 @@ class Application extends BaseModel $workdir = $this->workdir(); if (str($workdir)->endsWith($this->uuid)) { ray('Deleting workdir'); - instant_remote_process(['rm -rf '.$this->workdir()], $server, false); + instant_remote_process(['rm -rf ' . $this->workdir()], $server, false); } } @@ -173,6 +173,15 @@ class Application extends BaseModel } } + public function delete_connected_networks($uuid) + { + $server = data_get($this, 'destination.server'); + ray($uuid); + instant_remote_process(["docker network disconnect {$uuid} coolify-proxy"], $server, false); + instant_remote_process(["docker network rm {$uuid}"], $server, false); + } + + public function additional_servers() { return $this->belongsToMany(Server::class, 'additional_destinations') @@ -280,7 +289,7 @@ class Application extends BaseModel public function publishDirectory(): Attribute { return Attribute::make( - set: fn ($value) => $value ? '/'.ltrim($value, '/') : null, + set: fn ($value) => $value ? '/' . ltrim($value, '/') : null, ); } @@ -288,7 +297,7 @@ class Application extends BaseModel { return Attribute::make( get: function () { - if (! is_null($this->source?->html_url) && ! is_null($this->git_repository) && ! is_null($this->git_branch)) { + if (!is_null($this->source?->html_url) && !is_null($this->git_repository) && !is_null($this->git_branch)) { if (str($this->git_repository)->contains('bitbucket')) { return "{$this->source->html_url}/{$this->git_repository}/src/{$this->git_branch}"; } @@ -315,7 +324,7 @@ class Application extends BaseModel { return Attribute::make( get: function () { - if (! is_null($this->source?->html_url) && ! is_null($this->git_repository) && ! is_null($this->git_branch)) { + if (!is_null($this->source?->html_url) && !is_null($this->git_repository) && !is_null($this->git_branch)) { return "{$this->source->html_url}/{$this->git_repository}/settings/hooks"; } // Convert the SSH URL to HTTPS URL @@ -334,7 +343,7 @@ class Application extends BaseModel { return Attribute::make( get: function () { - if (! is_null($this->source?->html_url) && ! is_null($this->git_repository) && ! is_null($this->git_branch)) { + if (!is_null($this->source?->html_url) && !is_null($this->git_repository) && !is_null($this->git_branch)) { return "{$this->source->html_url}/{$this->git_repository}/commits/{$this->git_branch}"; } // Convert the SSH URL to HTTPS URL @@ -351,7 +360,7 @@ class Application extends BaseModel public function gitCommitLink($link): string { - if (! is_null(data_get($this, 'source.html_url')) && ! is_null(data_get($this, 'git_repository')) && ! is_null(data_get($this, 'git_branch'))) { + if (!is_null(data_get($this, 'source.html_url')) && !is_null(data_get($this, 'git_repository')) && !is_null(data_get($this, 'git_branch'))) { if (str($this->source->html_url)->contains('bitbucket')) { return "{$this->source->html_url}/{$this->git_repository}/commits/{$link}"; } @@ -362,7 +371,7 @@ class Application extends BaseModel $git_repository = str_replace('.git', '', $this->git_repository); $url = Url::fromString($git_repository); $url = $url->withUserInfo(''); - $url = $url->withPath($url->getPath().'/commits/'.$link); + $url = $url->withPath($url->getPath() . '/commits/' . $link); return $url->__toString(); } @@ -432,7 +441,7 @@ class Application extends BaseModel public function baseDirectory(): Attribute { return Attribute::make( - set: fn ($value) => '/'.ltrim($value, '/'), + set: fn ($value) => '/' . ltrim($value, '/'), ); } @@ -775,7 +784,7 @@ class Application extends BaseModel public function workdir() { - return application_configuration_dir()."/{$this->uuid}"; + return application_configuration_dir() . "/{$this->uuid}"; } public function isLogDrainEnabled() @@ -785,7 +794,7 @@ class Application extends BaseModel public function isConfigurationChanged(bool $save = false) { - $newConfigHash = $this->fqdn.$this->git_repository.$this->git_branch.$this->git_commit_sha.$this->build_pack.$this->static_image.$this->install_command.$this->build_command.$this->start_command.$this->ports_exposes.$this->ports_mappings.$this->base_directory.$this->publish_directory.$this->dockerfile.$this->dockerfile_location.$this->custom_labels.$this->custom_docker_run_options.$this->dockerfile_target_build.$this->redirect; + $newConfigHash = $this->fqdn . $this->git_repository . $this->git_branch . $this->git_commit_sha . $this->build_pack . $this->static_image . $this->install_command . $this->build_command . $this->start_command . $this->ports_exposes . $this->ports_mappings . $this->base_directory . $this->publish_directory . $this->dockerfile . $this->dockerfile_location . $this->custom_labels . $this->custom_docker_run_options . $this->dockerfile_target_build . $this->redirect; if ($this->pull_request_id === 0 || $this->pull_request_id === null) { $newConfigHash .= json_encode($this->environment_variables()->get('value')->sort()); } else { @@ -839,7 +848,7 @@ class Application extends BaseModel public function dirOnServer() { - return application_configuration_dir()."/{$this->uuid}"; + return application_configuration_dir() . "/{$this->uuid}"; } public function setGitImportSettings(string $deployment_uuid, string $git_clone_command, bool $public = false) @@ -885,7 +894,7 @@ class Application extends BaseModel if ($this->source->is_public) { $fullRepoUrl = "{$this->source->html_url}/{$customRepository}"; $git_clone_command = "{$git_clone_command} {$this->source->html_url}/{$customRepository} {$baseDir}"; - if (! $only_checkout) { + if (!$only_checkout) { $git_clone_command = $this->setGitImportSettings($deployment_uuid, $git_clone_command, public: true); } if ($exec_in_docker) { @@ -902,7 +911,7 @@ class Application extends BaseModel $git_clone_command = "{$git_clone_command} $source_html_url_scheme://x-access-token:$github_access_token@$source_html_url_host/{$customRepository} {$baseDir}"; $fullRepoUrl = "$source_html_url_scheme://x-access-token:$github_access_token@$source_html_url_host/{$customRepository}"; } - if (! $only_checkout) { + if (!$only_checkout) { $git_clone_command = $this->setGitImportSettings($deployment_uuid, $git_clone_command, public: false); } if ($exec_in_docker) { @@ -963,7 +972,7 @@ class Application extends BaseModel } else { $commands->push("echo 'Checking out $branch'"); } - $git_clone_command = "{$git_clone_command} && cd {$baseDir} && GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$customPort} -o Port={$customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" git fetch origin $branch && ".$this->buildGitCheckoutCommand($pr_branch_name); + $git_clone_command = "{$git_clone_command} && cd {$baseDir} && GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$customPort} -o Port={$customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" git fetch origin $branch && " . $this->buildGitCheckoutCommand($pr_branch_name); } elseif ($git_type === 'github' || $git_type === 'gitea') { $branch = "pull/{$pull_request_id}/head:$pr_branch_name"; if ($exec_in_docker) { @@ -971,14 +980,14 @@ class Application extends BaseModel } else { $commands->push("echo 'Checking out $branch'"); } - $git_clone_command = "{$git_clone_command} && cd {$baseDir} && GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$customPort} -o Port={$customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" git fetch origin $branch && ".$this->buildGitCheckoutCommand($pr_branch_name); + $git_clone_command = "{$git_clone_command} && cd {$baseDir} && GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$customPort} -o Port={$customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" git fetch origin $branch && " . $this->buildGitCheckoutCommand($pr_branch_name); } elseif ($git_type === 'bitbucket') { if ($exec_in_docker) { $commands->push(executeInDocker($deployment_uuid, "echo 'Checking out $branch'")); } else { $commands->push("echo 'Checking out $branch'"); } - $git_clone_command = "{$git_clone_command} && cd {$baseDir} && GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$customPort} -o Port={$customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" ".$this->buildGitCheckoutCommand($commit); + $git_clone_command = "{$git_clone_command} && cd {$baseDir} && GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$customPort} -o Port={$customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" " . $this->buildGitCheckoutCommand($commit); } } @@ -1007,7 +1016,7 @@ class Application extends BaseModel } else { $commands->push("echo 'Checking out $branch'"); } - $git_clone_command = "{$git_clone_command} && cd {$baseDir} && GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$customPort} -o Port={$customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" git fetch origin $branch && ".$this->buildGitCheckoutCommand($pr_branch_name); + $git_clone_command = "{$git_clone_command} && cd {$baseDir} && GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$customPort} -o Port={$customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" git fetch origin $branch && " . $this->buildGitCheckoutCommand($pr_branch_name); } elseif ($git_type === 'github' || $git_type === 'gitea') { $branch = "pull/{$pull_request_id}/head:$pr_branch_name"; if ($exec_in_docker) { @@ -1015,14 +1024,14 @@ class Application extends BaseModel } else { $commands->push("echo 'Checking out $branch'"); } - $git_clone_command = "{$git_clone_command} && cd {$baseDir} && GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$customPort} -o Port={$customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" git fetch origin $branch && ".$this->buildGitCheckoutCommand($pr_branch_name); + $git_clone_command = "{$git_clone_command} && cd {$baseDir} && GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$customPort} -o Port={$customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" git fetch origin $branch && " . $this->buildGitCheckoutCommand($pr_branch_name); } elseif ($git_type === 'bitbucket') { if ($exec_in_docker) { $commands->push(executeInDocker($deployment_uuid, "echo 'Checking out $branch'")); } else { $commands->push("echo 'Checking out $branch'"); } - $git_clone_command = "{$git_clone_command} && cd {$baseDir} && GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$customPort} -o Port={$customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" ".$this->buildGitCheckoutCommand($commit); + $git_clone_command = "{$git_clone_command} && cd {$baseDir} && GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$customPort} -o Port={$customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" " . $this->buildGitCheckoutCommand($commit); } } @@ -1074,20 +1083,20 @@ class Application extends BaseModel } if ($source->startsWith('.')) { $source = $source->after('.'); - $source = $workdir.$source; + $source = $workdir . $source; } $commands->push("mkdir -p $source > /dev/null 2>&1 || true"); } } } $labels = collect(data_get($service, 'labels', [])); - if (! $labels->contains('coolify.managed')) { + if (!$labels->contains('coolify.managed')) { $labels->push('coolify.managed=true'); } - if (! $labels->contains('coolify.applicationId')) { - $labels->push('coolify.applicationId='.$this->id); + if (!$labels->contains('coolify.applicationId')) { + $labels->push('coolify.applicationId=' . $this->id); } - if (! $labels->contains('coolify.type')) { + if (!$labels->contains('coolify.type')) { $labels->push('coolify.type=application'); } data_set($service, 'labels', $labels->toArray()); @@ -1161,7 +1170,7 @@ class Application extends BaseModel $jsonNames = $json->keys()->toArray(); $diff = array_diff($jsonNames, $names); $json = $json->filter(function ($value, $key) use ($diff) { - return ! in_array($key, $diff); + return !in_array($key, $diff); }); if ($json) { $this->docker_compose_domains = json_encode($json); @@ -1178,13 +1187,12 @@ class Application extends BaseModel } else { throw new \RuntimeException("Docker Compose file not found at: $workdir$composeFile

Check if you used the right extension (.yaml or .yml) in the compose file name."); } - } public function parseContainerLabels(?ApplicationPreview $preview = null) { $customLabels = data_get($this, 'custom_labels'); - if (! $customLabels) { + if (!$customLabels) { return; } if (base64_encode(base64_decode($customLabels, true)) !== $customLabels) { @@ -1267,10 +1275,10 @@ class Application extends BaseModel continue; } if (isset($healthcheckCommand) && str_contains($trimmedLine, '\\')) { - $healthcheckCommand .= ' '.trim($trimmedLine, '\\ '); + $healthcheckCommand .= ' ' . trim($trimmedLine, '\\ '); } - if (isset($healthcheckCommand) && ! str_contains($trimmedLine, '\\') && ! empty($healthcheckCommand)) { - $healthcheckCommand .= ' '.$trimmedLine; + if (isset($healthcheckCommand) && !str_contains($trimmedLine, '\\') && !empty($healthcheckCommand)) { + $healthcheckCommand .= ' ' . $trimmedLine; break; } } diff --git a/app/Models/ServiceApplication.php b/app/Models/ServiceApplication.php index 6690f254e..9df825869 100644 --- a/app/Models/ServiceApplication.php +++ b/app/Models/ServiceApplication.php @@ -23,7 +23,7 @@ class ServiceApplication extends BaseModel public function restart() { - $container_id = $this->name.'-'.$this->service->uuid; + $container_id = $this->name . '-' . $this->service->uuid; instant_remote_process(["docker restart {$container_id}"], $this->service->server); } @@ -59,7 +59,7 @@ class ServiceApplication extends BaseModel public function workdir() { - return service_configuration_dir()."/{$this->service->uuid}"; + return service_configuration_dir() . "/{$this->service->uuid}"; } public function serviceType() diff --git a/resources/views/livewire/project/shared/danger.blade.php b/resources/views/livewire/project/shared/danger.blade.php index 20bd7310b..f9eaec30f 100644 --- a/resources/views/livewire/project/shared/danger.blade.php +++ b/resources/views/livewire/project/shared/danger.blade.php @@ -9,10 +9,9 @@
This resource will be deleted. It is not reversible. Please think again.

Actions

- - - - + + + + \ No newline at end of file From 70aa05bde96a7a9a26d40903fc3dc81d3ba6e074 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 9 Aug 2024 00:42:23 +0200 Subject: [PATCH 028/863] order in importance --- resources/views/livewire/project/shared/danger.blade.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/views/livewire/project/shared/danger.blade.php b/resources/views/livewire/project/shared/danger.blade.php index f9eaec30f..6d00f357c 100644 --- a/resources/views/livewire/project/shared/danger.blade.php +++ b/resources/views/livewire/project/shared/danger.blade.php @@ -9,9 +9,9 @@
This resource will be deleted. It is not reversible. Please think again.

Actions

- - + + \ No newline at end of file From 51071da7006c7b15cc8f6828a8586d6678a072a4 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 9 Aug 2024 01:00:07 +0200 Subject: [PATCH 029/863] fix order --- app/Jobs/DeleteResourceJob.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/Jobs/DeleteResourceJob.php b/app/Jobs/DeleteResourceJob.php index 68036ee4a..50e0e646e 100644 --- a/app/Jobs/DeleteResourceJob.php +++ b/app/Jobs/DeleteResourceJob.php @@ -64,13 +64,12 @@ class DeleteResourceJob implements ShouldBeEncrypted, ShouldQueue break; } - if ($this->deleteConfigurations) { - $this->resource?->delete_configurations(); - } - if ($this->deleteVolumes && $this->resource->type() !== 'service') { $this->resource?->delete_volumes($persistentStorages); } + if ($this->deleteConfigurations) { + $this->resource?->delete_configurations(); + } $server = data_get($this->resource, 'server'); if ($this->deleteImages && $server) { From 86a087056e289873b474dacf0dd063b2b5e285cd Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 9 Aug 2024 02:11:42 +0200 Subject: [PATCH 030/863] fix volume deletion for services --- app/Actions/Service/DeleteService.php | 46 ++++++++++--------- .../livewire/project/shared/danger.blade.php | 2 +- 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/app/Actions/Service/DeleteService.php b/app/Actions/Service/DeleteService.php index f32a44262..13b5cc50b 100644 --- a/app/Actions/Service/DeleteService.php +++ b/app/Actions/Service/DeleteService.php @@ -14,12 +14,10 @@ class DeleteService { try { $server = data_get($service, 'server'); - - if ($server->isFunctional()) { + if ($deleteVolumes && $server->isFunctional()) { $storagesToDelete = collect([]); $service->environment_variables()->delete(); - $commands = []; foreach ($service->applications()->get() as $application) { $storages = $application->persistentStorages()->get(); @@ -33,27 +31,33 @@ class DeleteService $storagesToDelete->push($storage); } } - - // Delete volumes if the flag is set - if ($deleteVolumes) { - foreach ($service->applications()->get() as $application) { - $persistentStorages = $application->persistentStorages()->get(); - $application->delete_volumes($persistentStorages); - } + foreach ($storagesToDelete as $storage) { + $commands[] = "docker volume rm -f $storage->name"; } - // Delete networks if the flag is set - if ($deleteConnectedNetworks) { - $uuid = $service->uuid; - $service->delete_connected_networks($uuid); - } - - // Command to remove the service itself - $commands[] = "docker rm -f $service->uuid"; - // Execute all commands - instant_remote_process($commands, $server, false); + if (!empty($commands)) { + foreach ($commands as $command) { + $result = instant_remote_process([$command], $server, false); + if ($result !== 0) { + ray("Failed to execute: $command"); + } + } + } } + + // Delete networks if the flag is set + if ($deleteConnectedNetworks) { + $uuid = $service->uuid; + $service->delete_connected_networks($uuid); + } + + // Command to remove the service itself + $commands[] = "docker rm -f $service->uuid"; + + // Execute all commands + instant_remote_process($commands, $server, false); + } catch (\Exception $e) { throw new \Exception($e->getMessage()); } finally { @@ -79,4 +83,4 @@ class DeleteService } } } -} +} \ No newline at end of file diff --git a/resources/views/livewire/project/shared/danger.blade.php b/resources/views/livewire/project/shared/danger.blade.php index 6d00f357c..174731eea 100644 --- a/resources/views/livewire/project/shared/danger.blade.php +++ b/resources/views/livewire/project/shared/danger.blade.php @@ -10,7 +10,7 @@ again.

Actions

- + From e67e03f73f2c8405b9bb96d6c1adb3f27c1b7e48 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 9 Aug 2024 02:15:40 +0200 Subject: [PATCH 031/863] added comments and removed temp ones --- app/Actions/Service/DeleteService.php | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/app/Actions/Service/DeleteService.php b/app/Actions/Service/DeleteService.php index 13b5cc50b..521a70e83 100644 --- a/app/Actions/Service/DeleteService.php +++ b/app/Actions/Service/DeleteService.php @@ -35,7 +35,7 @@ class DeleteService $commands[] = "docker volume rm -f $storage->name"; } - // Execute all commands + // Execute volume deletion first, this must be done first otherwise volumes will not be deleted. if (!empty($commands)) { foreach ($commands as $command) { $result = instant_remote_process([$command], $server, false); @@ -46,22 +46,18 @@ class DeleteService } } - // Delete networks if the flag is set if ($deleteConnectedNetworks) { $uuid = $service->uuid; $service->delete_connected_networks($uuid); } - // Command to remove the service itself $commands[] = "docker rm -f $service->uuid"; - // Execute all commands + // Executing remaining commands instant_remote_process($commands, $server, false); - } catch (\Exception $e) { throw new \Exception($e->getMessage()); } finally { - // Delete configurations if the flag is set if ($deleteConfigurations) { $service->delete_configurations(); } @@ -77,10 +73,9 @@ class DeleteService $service->tags()->detach(); $service->forceDelete(); - // Run cleanup if images need to be deleted if ($deleteImages) { CleanupDocker::run($server, true); } } } -} \ No newline at end of file +} From 7722809c52a04f052bfd1d2632daaf88ca0527a7 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 9 Aug 2024 02:20:32 +0200 Subject: [PATCH 032/863] typo --- resources/views/livewire/project/shared/danger.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/livewire/project/shared/danger.blade.php b/resources/views/livewire/project/shared/danger.blade.php index 174731eea..1e1365749 100644 --- a/resources/views/livewire/project/shared/danger.blade.php +++ b/resources/views/livewire/project/shared/danger.blade.php @@ -10,7 +10,7 @@ again.

Actions

- + From 53dff4ca4f6f34f2d47de2db4e9c960275da1a34 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 9 Aug 2024 02:58:59 +0200 Subject: [PATCH 033/863] simplify uuid variabel --- app/Actions/Service/DeleteService.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Actions/Service/DeleteService.php b/app/Actions/Service/DeleteService.php index 521a70e83..186200993 100644 --- a/app/Actions/Service/DeleteService.php +++ b/app/Actions/Service/DeleteService.php @@ -47,14 +47,14 @@ class DeleteService } if ($deleteConnectedNetworks) { - $uuid = $service->uuid; - $service->delete_connected_networks($uuid); + $service->delete_connected_networks($service->uuid); } $commands[] = "docker rm -f $service->uuid"; // Executing remaining commands instant_remote_process($commands, $server, false); + } catch (\Exception $e) { throw new \Exception($e->getMessage()); } finally { From d980c7a4254900d4c98fefd84f2cc257e2128356 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 9 Aug 2024 02:59:41 +0200 Subject: [PATCH 034/863] only run network removal on stop service if it is not a deletion operation --- app/Actions/Service/StopService.php | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/app/Actions/Service/StopService.php b/app/Actions/Service/StopService.php index 3dd91b4e2..e7d108528 100644 --- a/app/Actions/Service/StopService.php +++ b/app/Actions/Service/StopService.php @@ -9,14 +9,14 @@ class StopService { use AsAction; - public function handle(Service $service) + public function handle(Service $service, bool $isDeleteOperation = false) { try { $server = $service->destination->server; - if (! $server->isFunctional()) { + if (!$server->isFunctional()) { return 'Server is not functional'; } - ray('Stopping service: '.$service->name); + ray('Stopping service: ' . $service->name); $applications = $service->applications()->get(); foreach ($applications as $application) { instant_remote_process(command: ["docker stop --time=30 {$application->name}-{$service->uuid}"], server: $server, throwError: false); @@ -31,13 +31,15 @@ class StopService instant_remote_process(command: ["docker rm -f {$db->name}-{$service->uuid}"], server: $server, throwError: false); $db->update(['status' => 'exited']); } - instant_remote_process(["docker network disconnect {$service->uuid} coolify-proxy"], $service->server); - instant_remote_process(["docker network rm {$service->uuid}"], $service->server); + + if (!$isDeleteOperation) { + // Only run this if not a delete operation + $service->delete_connected_networks($service->uuid); + } } catch (\Exception $e) { ray($e->getMessage()); return $e->getMessage(); } - } } From 97c2bedda27f9078c794ac952332681f1b2e5024 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 9 Aug 2024 03:00:30 +0200 Subject: [PATCH 035/863] add delete_connected_networks function to services.php --- app/Models/Application.php | 2 -- app/Models/Service.php | 15 +++++++++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/app/Models/Application.php b/app/Models/Application.php index 324713bbf..d88e94e19 100644 --- a/app/Models/Application.php +++ b/app/Models/Application.php @@ -151,7 +151,6 @@ class Application extends BaseModel $server = data_get($this, 'destination.server'); $workdir = $this->workdir(); if (str($workdir)->endsWith($this->uuid)) { - ray('Deleting workdir'); instant_remote_process(['rm -rf ' . $this->workdir()], $server, false); } } @@ -176,7 +175,6 @@ class Application extends BaseModel public function delete_connected_networks($uuid) { $server = data_get($this, 'destination.server'); - ray($uuid); instant_remote_process(["docker network disconnect {$uuid} coolify-proxy"], $server, false); instant_remote_process(["docker network rm {$uuid}"], $server, false); } diff --git a/app/Models/Service.php b/app/Models/Service.php index 33238281e..f56d05af1 100644 --- a/app/Models/Service.php +++ b/app/Models/Service.php @@ -56,7 +56,7 @@ class Service extends BaseModel $databaseStorages = $this->databases()->get()->pluck('persistentStorages')->flatten()->sortBy('id'); $storages = $applicationStorages->merge($databaseStorages)->implode('updated_at'); - $newConfigHash = $images.$domains.$images.$storages; + $newConfigHash = $images . $domains . $images . $storages; $newConfigHash .= json_encode($this->environment_variables()->get('value')->sort()); $newConfigHash = md5($newConfigHash); $oldConfigHash = data_get($this, 'config_hash'); @@ -121,13 +121,20 @@ class Service extends BaseModel public function delete_configurations() { - $server = data_get($this, 'server'); + $server = data_get($this, 'destination.server'); $workdir = $this->workdir(); if (str($workdir)->endsWith($this->uuid)) { - instant_remote_process(['rm -rf '.$this->workdir()], $server, false); + instant_remote_process(['rm -rf ' . $this->workdir()], $server, false); } } + public function delete_connected_networks($uuid) + { + $server = data_get($this, 'destination.server'); + instant_remote_process(["docker network disconnect {$uuid} coolify-proxy"], $server, false); + instant_remote_process(["docker network rm {$uuid}"], $server, false); + } + public function status() { $applications = $this->applications; @@ -907,7 +914,7 @@ class Service extends BaseModel public function workdir() { - return service_configuration_dir()."/{$this->uuid}"; + return service_configuration_dir() . "/{$this->uuid}"; } public function saveComposeConfigs() From 5595853379307589cf0b50dc4c573028ded651df Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 9 Aug 2024 03:03:40 +0200 Subject: [PATCH 036/863] WIP database network, image removal --- app/Jobs/DeleteResourceJob.php | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/app/Jobs/DeleteResourceJob.php b/app/Jobs/DeleteResourceJob.php index 50e0e646e..6e102266a 100644 --- a/app/Jobs/DeleteResourceJob.php +++ b/app/Jobs/DeleteResourceJob.php @@ -57,9 +57,19 @@ class DeleteResourceJob implements ShouldBeEncrypted, ShouldQueue case 'standalone-clickhouse': $persistentStorages = $this->resource?->persistentStorages()?->get(); StopDatabase::run($this->resource); + // TODO + // DBs do not have a network normally? + //if ($this->deleteConnectedNetworks) { + // $this->resource?->delete_connected_networks($this->resource->uuid); + // } + // } + // $server = data_get($this->resource, 'server'); + // if ($this->deleteImages && $server) { + // CleanupDocker::run($server, true); + // } break; case 'service': - StopService::run($this->resource); + StopService::run($this->resource, true); DeleteService::run($this->resource, $this->deleteConfigurations, $this->deleteVolumes, $this->deleteImages, $this->deleteConnectedNetworks); break; } @@ -77,8 +87,7 @@ class DeleteResourceJob implements ShouldBeEncrypted, ShouldQueue } if ($this->deleteConnectedNetworks) { - $uuid = $this->resource->uuid; // Get the UUID from the resource - $this->resource?->delete_connected_networks($uuid); // Pass the UUID to the method + $this->resource?->delete_connected_networks($this->resource->uuid); } } catch (\Throwable $e) { send_internal_notification('ContainerStoppingJob failed with: ' . $e->getMessage()); From d177e49e62abfee19f4da56f8c01b6b29ab3974f Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 9 Aug 2024 18:43:13 +0200 Subject: [PATCH 037/863] updated warning message and formating --- .../livewire/project/service/navbar.blade.php | 208 +++++++++--------- 1 file changed, 100 insertions(+), 108 deletions(-) diff --git a/resources/views/livewire/project/service/navbar.blade.php b/resources/views/livewire/project/service/navbar.blade.php index 125f9121a..67d6a78ca 100644 --- a/resources/views/livewire/project/service/navbar.blade.php +++ b/resources/views/livewire/project/service/navbar.blade.php @@ -10,130 +10,122 @@ @script - + @endscript From 72bcf03cbb942b49891e4683b3479cbf5441382d Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 9 Aug 2024 18:59:41 +0200 Subject: [PATCH 038/863] graceful service container stop --- app/Actions/Service/StopService.php | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/app/Actions/Service/StopService.php b/app/Actions/Service/StopService.php index e7d108528..933eca7d4 100644 --- a/app/Actions/Service/StopService.php +++ b/app/Actions/Service/StopService.php @@ -3,6 +3,7 @@ namespace App\Actions\Service; use App\Models\Service; +use App\Actions\Server\CleanupDocker; use Lorisleiva\Actions\Concerns\AsAction; class StopService @@ -19,27 +20,38 @@ class StopService ray('Stopping service: ' . $service->name); $applications = $service->applications()->get(); foreach ($applications as $application) { - instant_remote_process(command: ["docker stop --time=30 {$application->name}-{$service->uuid}"], server: $server, throwError: false); - instant_remote_process(command: ["docker rm {$application->name}-{$service->uuid}"], server: $server, throwError: false); - instant_remote_process(command: ["docker rm -f {$application->name}-{$service->uuid}"], server: $server, throwError: false); + $this->stopContainer("{$application->name}-{$service->uuid}", $server, 600); $application->update(['status' => 'exited']); } $dbs = $service->databases()->get(); foreach ($dbs as $db) { - instant_remote_process(command: ["docker stop --time=30 {$db->name}-{$service->uuid}"], server: $server, throwError: false); - instant_remote_process(command: ["docker rm {$db->name}-{$service->uuid}"], server: $server, throwError: false); - instant_remote_process(command: ["docker rm -f {$db->name}-{$service->uuid}"], server: $server, throwError: false); + $this->stopContainer("{$db->name}-{$service->uuid}", $server, 600); $db->update(['status' => 'exited']); } if (!$isDeleteOperation) { - // Only run this if not a delete operation + // Only run if not a deletion operation as for deletion we can specify if we want to delete networks or not $service->delete_connected_networks($service->uuid); + CleanupDocker::run($server, true); } } catch (\Exception $e) { ray($e->getMessage()); - return $e->getMessage(); } } + + private function stopContainer(string $containerName, $server, int $timeout = 600) + { + try { + instant_remote_process(command: ["docker stop --time=$timeout $containerName"], server: $server, throwError: false); + $isRunning = instant_remote_process(command: ["docker inspect -f '{{.State.Running}}' $containerName"], server: $server, throwError: false); + + if (trim($isRunning) === 'true') { + instant_remote_process(command: ["docker kill $containerName"], server: $server, throwError: false); + } + } catch (\Exception $error) { + } + + instant_remote_process(command: ["docker rm -f $containerName"], server: $server, throwError: false); + } } From 1cfddfd529025e8623cd8ca9b2cdba334fbf8a3f Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 9 Aug 2024 19:17:58 +0200 Subject: [PATCH 039/863] fix stop large amount of containers --- app/Actions/Service/StopService.php | 76 +++++++++++++++++++++-------- 1 file changed, 57 insertions(+), 19 deletions(-) diff --git a/app/Actions/Service/StopService.php b/app/Actions/Service/StopService.php index 933eca7d4..035781885 100644 --- a/app/Actions/Service/StopService.php +++ b/app/Actions/Service/StopService.php @@ -5,6 +5,8 @@ namespace App\Actions\Service; use App\Models\Service; use App\Actions\Server\CleanupDocker; use Lorisleiva\Actions\Concerns\AsAction; +use Illuminate\Support\Facades\Process; +use Illuminate\Process\InvokedProcess; class StopService { @@ -18,19 +20,12 @@ class StopService return 'Server is not functional'; } ray('Stopping service: ' . $service->name); - $applications = $service->applications()->get(); - foreach ($applications as $application) { - $this->stopContainer("{$application->name}-{$service->uuid}", $server, 600); - $application->update(['status' => 'exited']); - } - $dbs = $service->databases()->get(); - foreach ($dbs as $db) { - $this->stopContainer("{$db->name}-{$service->uuid}", $server, 600); - $db->update(['status' => 'exited']); - } + + $containersToStop = $this->getContainersToStop($service); + + $this->stopContainers($containersToStop, $server); if (!$isDeleteOperation) { - // Only run if not a deletion operation as for deletion we can specify if we want to delete networks or not $service->delete_connected_networks($service->uuid); CleanupDocker::run($server, true); } @@ -40,18 +35,61 @@ class StopService } } - private function stopContainer(string $containerName, $server, int $timeout = 600) + private function getContainersToStop(Service $service): array { - try { - instant_remote_process(command: ["docker stop --time=$timeout $containerName"], server: $server, throwError: false); - $isRunning = instant_remote_process(command: ["docker inspect -f '{{.State.Running}}' $containerName"], server: $server, throwError: false); + $containersToStop = []; + $applications = $service->applications()->get(); + foreach ($applications as $application) { + $containersToStop[] = "{$application->name}-{$service->uuid}"; + } + $dbs = $service->databases()->get(); + foreach ($dbs as $db) { + $containersToStop[] = "{$db->name}-{$service->uuid}"; + } + return $containersToStop; + } - if (trim($isRunning) === 'true') { - instant_remote_process(command: ["docker kill $containerName"], server: $server, throwError: false); - } - } catch (\Exception $error) { + private function stopContainers(array $containerNames, $server, int $timeout = 300) + { + $processes = []; + foreach ($containerNames as $containerName) { + $processes[$containerName] = $this->stopContainer($containerName, $server, $timeout); } + $startTime = time(); + while (count($processes) > 0) { + $finishedProcesses = array_filter($processes, function ($process) { + return !$process->running(); + }); + foreach ($finishedProcesses as $containerName => $process) { + unset($processes[$containerName]); + $this->removeContainer($containerName, $server); + } + + if (time() - $startTime >= $timeout) { + $this->forceStopRemainingContainers(array_keys($processes), $server); + break; + } + + usleep(100000); + } + } + + private function stopContainer(string $containerName, $server, int $timeout): InvokedProcess + { + return Process::timeout($timeout)->start("docker stop --time=$timeout $containerName"); + } + + private function removeContainer(string $containerName, $server) + { instant_remote_process(command: ["docker rm -f $containerName"], server: $server, throwError: false); } + + private function forceStopRemainingContainers(array $containerNames, $server) + { + foreach ($containerNames as $containerName) { + instant_remote_process(command: ["docker kill $containerName"], server: $server, throwError: false); + $this->removeContainer($containerName, $server); + } + } } From a4bb87d13b5ac132c634feec986537aab93b3ad1 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 9 Aug 2024 19:22:14 +0200 Subject: [PATCH 040/863] simplify DeleteService.php --- app/Actions/Service/DeleteService.php | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/Actions/Service/DeleteService.php b/app/Actions/Service/DeleteService.php index 186200993..238e6b954 100644 --- a/app/Actions/Service/DeleteService.php +++ b/app/Actions/Service/DeleteService.php @@ -50,11 +50,7 @@ class DeleteService $service->delete_connected_networks($service->uuid); } - $commands[] = "docker rm -f $service->uuid"; - - // Executing remaining commands - instant_remote_process($commands, $server, false); - + instant_remote_process(["docker rm -f $service->uuid"], $server, throwError: false); } catch (\Exception $e) { throw new \Exception($e->getMessage()); } finally { From 450351921eeae0f98f6b2ba157a16b8cf83e561b Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 9 Aug 2024 19:39:21 +0200 Subject: [PATCH 041/863] added public functions --- app/Models/Application.php | 55 ++++++++++++++++++++++++++++++++++++++ app/Models/Service.php | 55 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) diff --git a/app/Models/Application.php b/app/Models/Application.php index d88e94e19..2873ee7da 100644 --- a/app/Models/Application.php +++ b/app/Models/Application.php @@ -8,6 +8,8 @@ use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Support\Collection; use Illuminate\Support\Str; +use Illuminate\Support\Facades\Process; +use Illuminate\Process\InvokedProcess; use OpenApi\Attributes as OA; use RuntimeException; use Spatie\Activitylog\Models\Activity; @@ -146,6 +148,59 @@ class Application extends BaseModel return Application::whereRelation('environment.project.team', 'id', $teamId)->orderBy('name'); } + public function getContainersToStop(bool $previewDeployments = false): array + { + $containers = $previewDeployments + ? getCurrentApplicationContainerStatus($this->destination->server, $this->id, includePullrequests: true) + : getCurrentApplicationContainerStatus($this->destination->server, $this->id, 0); + + return $containers->pluck('Names')->toArray(); + } + + public function stopContainers(array $containerNames, $server, int $timeout = 600) + { + $processes = []; + foreach ($containerNames as $containerName) { + $processes[$containerName] = $this->stopContainer($containerName, $server, $timeout); + } + + $startTime = time(); + while (count($processes) > 0) { + $finishedProcesses = array_filter($processes, function ($process) { + return !$process->running(); + }); + foreach ($finishedProcesses as $containerName => $process) { + unset($processes[$containerName]); + $this->removeContainer($containerName, $server); + } + + if (time() - $startTime >= $timeout) { + $this->forceStopRemainingContainers(array_keys($processes), $server); + break; + } + + usleep(100000); + } + } + + public function stopContainer(string $containerName, $server, int $timeout): InvokedProcess + { + return Process::timeout($timeout)->start("docker stop --time=$timeout $containerName"); + } + + public function removeContainer(string $containerName, $server) + { + instant_remote_process(command: ["docker rm -f $containerName"], server: $server, throwError: false); + } + + public function forceStopRemainingContainers(array $containerNames, $server) + { + foreach ($containerNames as $containerName) { + instant_remote_process(command: ["docker kill $containerName"], server: $server, throwError: false); + $this->removeContainer($containerName, $server); + } + } + public function delete_configurations() { $server = data_get($this, 'destination.server'); diff --git a/app/Models/Service.php b/app/Models/Service.php index f56d05af1..14213ee9a 100644 --- a/app/Models/Service.php +++ b/app/Models/Service.php @@ -7,6 +7,8 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Support\Collection; +use Illuminate\Support\Facades\Process; +use Illuminate\Process\InvokedProcess; use OpenApi\Attributes as OA; use Spatie\Url\Url; use Symfony\Component\Yaml\Yaml; @@ -119,6 +121,59 @@ class Service extends BaseModel return $this->morphToMany(Tag::class, 'taggable'); } + public function getContainersToStop(bool $previewDeployments = false): array + { + $containers = $previewDeployments + ? getCurrentApplicationContainerStatus($this->destination->server, $this->id, includePullrequests: true) + : getCurrentApplicationContainerStatus($this->destination->server, $this->id, 0); + + return $containers->pluck('Names')->toArray(); + } + + public function stopContainers(array $containerNames, $server, int $timeout = 600) + { + $processes = []; + foreach ($containerNames as $containerName) { + $processes[$containerName] = $this->stopContainer($containerName, $server, $timeout); + } + + $startTime = time(); + while (count($processes) > 0) { + $finishedProcesses = array_filter($processes, function ($process) { + return !$process->running(); + }); + foreach ($finishedProcesses as $containerName => $process) { + unset($processes[$containerName]); + $this->removeContainer($containerName, $server); + } + + if (time() - $startTime >= $timeout) { + $this->forceStopRemainingContainers(array_keys($processes), $server); + break; + } + + usleep(100000); + } + } + + public function stopContainer(string $containerName, $server, int $timeout): InvokedProcess + { + return Process::timeout($timeout)->start("docker stop --time=$timeout $containerName"); + } + + public function removeContainer(string $containerName, $server) + { + instant_remote_process(command: ["docker rm -f $containerName"], server: $server, throwError: false); + } + + public function forceStopRemainingContainers(array $containerNames, $server) + { + foreach ($containerNames as $containerName) { + instant_remote_process(command: ["docker kill $containerName"], server: $server, throwError: false); + $this->removeContainer($containerName, $server); + } + } + public function delete_configurations() { $server = data_get($this, 'destination.server'); From 41be1f7666c67ce53afdf994427a9489d6d5fe96 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 9 Aug 2024 19:39:43 +0200 Subject: [PATCH 042/863] use public function --- app/Actions/Application/StopApplication.php | 45 +++++--------- app/Actions/Service/StopService.php | 65 +-------------------- 2 files changed, 18 insertions(+), 92 deletions(-) diff --git a/app/Actions/Application/StopApplication.php b/app/Actions/Application/StopApplication.php index 73abeba7a..5f5846f55 100644 --- a/app/Actions/Application/StopApplication.php +++ b/app/Actions/Application/StopApplication.php @@ -12,41 +12,28 @@ class StopApplication public function handle(Application $application, bool $previewDeployments = false) { - if ($application->destination->server->isSwarm()) { - instant_remote_process(["docker stack rm {$application->uuid}"], $application->destination->server); - return; - } - - $servers = collect([]); - $servers->push($application->destination->server); - $application->additional_servers->map(function ($server) use ($servers) { - $servers->push($server); - }); - foreach ($servers as $server) { + try { + $server = $application->destination->server; if (!$server->isFunctional()) { return 'Server is not functional'; } - if ($previewDeployments) { - $containers = getCurrentApplicationContainerStatus($server, $application->id, includePullrequests: true); - } else { - $containers = getCurrentApplicationContainerStatus($server, $application->id, 0); - } - if ($containers->count() > 0) { - foreach ($containers as $container) { - $containerName = data_get($container, 'Names'); - if ($containerName) { - instant_remote_process(command: ["docker stop --time=30 $containerName"], server: $server, throwError: false); - instant_remote_process(command: ["docker rm $containerName"], server: $server, throwError: false); - instant_remote_process(command: ["docker rm -f {$containerName}"], server: $server, throwError: false); - } - } - } - if ($application->build_pack === 'dockercompose') { - $uuid = $application->uuid; - $application->delete_connected_networks($uuid); + ray('Stopping application: ' . $application->name); + if ($server->isSwarm()) { + instant_remote_process(["docker stack rm {$application->uuid}"], $server); + return; + } + + $containersToStop = $application->getContainersToStop($previewDeployments); + $application->stopContainers($containersToStop, $server); + + if ($application->build_pack === 'dockercompose') { + $application->delete_connected_networks($application->uuid); CleanupDocker::run($server, true); } + } catch (\Exception $e) { + ray($e->getMessage()); + return $e->getMessage(); } } } diff --git a/app/Actions/Service/StopService.php b/app/Actions/Service/StopService.php index 035781885..6b348f830 100644 --- a/app/Actions/Service/StopService.php +++ b/app/Actions/Service/StopService.php @@ -5,8 +5,6 @@ namespace App\Actions\Service; use App\Models\Service; use App\Actions\Server\CleanupDocker; use Lorisleiva\Actions\Concerns\AsAction; -use Illuminate\Support\Facades\Process; -use Illuminate\Process\InvokedProcess; class StopService { @@ -21,9 +19,8 @@ class StopService } ray('Stopping service: ' . $service->name); - $containersToStop = $this->getContainersToStop($service); - - $this->stopContainers($containersToStop, $server); + $containersToStop = $service->getContainersToStop(); + $service->stopContainers($containersToStop, $server); if (!$isDeleteOperation) { $service->delete_connected_networks($service->uuid); @@ -34,62 +31,4 @@ class StopService return $e->getMessage(); } } - - private function getContainersToStop(Service $service): array - { - $containersToStop = []; - $applications = $service->applications()->get(); - foreach ($applications as $application) { - $containersToStop[] = "{$application->name}-{$service->uuid}"; - } - $dbs = $service->databases()->get(); - foreach ($dbs as $db) { - $containersToStop[] = "{$db->name}-{$service->uuid}"; - } - return $containersToStop; - } - - private function stopContainers(array $containerNames, $server, int $timeout = 300) - { - $processes = []; - foreach ($containerNames as $containerName) { - $processes[$containerName] = $this->stopContainer($containerName, $server, $timeout); - } - - $startTime = time(); - while (count($processes) > 0) { - $finishedProcesses = array_filter($processes, function ($process) { - return !$process->running(); - }); - foreach ($finishedProcesses as $containerName => $process) { - unset($processes[$containerName]); - $this->removeContainer($containerName, $server); - } - - if (time() - $startTime >= $timeout) { - $this->forceStopRemainingContainers(array_keys($processes), $server); - break; - } - - usleep(100000); - } - } - - private function stopContainer(string $containerName, $server, int $timeout): InvokedProcess - { - return Process::timeout($timeout)->start("docker stop --time=$timeout $containerName"); - } - - private function removeContainer(string $containerName, $server) - { - instant_remote_process(command: ["docker rm -f $containerName"], server: $server, throwError: false); - } - - private function forceStopRemainingContainers(array $containerNames, $server) - { - foreach ($containerNames as $containerName) { - instant_remote_process(command: ["docker kill $containerName"], server: $server, throwError: false); - $this->removeContainer($containerName, $server); - } - } } From 2ca6ffb84e59d3221fb5a6c4d320fae5c091988d Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 9 Aug 2024 19:57:53 +0200 Subject: [PATCH 043/863] fix public function service.php --- app/Actions/Service/StopService.php | 2 +- app/Models/Service.php | 25 +++++++++++++++---------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/app/Actions/Service/StopService.php b/app/Actions/Service/StopService.php index 6b348f830..85c61dc83 100644 --- a/app/Actions/Service/StopService.php +++ b/app/Actions/Service/StopService.php @@ -31,4 +31,4 @@ class StopService return $e->getMessage(); } } -} +} \ No newline at end of file diff --git a/app/Models/Service.php b/app/Models/Service.php index 14213ee9a..64796283c 100644 --- a/app/Models/Service.php +++ b/app/Models/Service.php @@ -121,20 +121,25 @@ class Service extends BaseModel return $this->morphToMany(Tag::class, 'taggable'); } - public function getContainersToStop(bool $previewDeployments = false): array + public function getContainersToStop(): array { - $containers = $previewDeployments - ? getCurrentApplicationContainerStatus($this->destination->server, $this->id, includePullrequests: true) - : getCurrentApplicationContainerStatus($this->destination->server, $this->id, 0); - - return $containers->pluck('Names')->toArray(); + $containersToStop = []; + $applications = $this->applications()->get(); + foreach ($applications as $application) { + $containersToStop[] = "{$application->name}-{$this->uuid}"; + } + $dbs = $this->databases()->get(); + foreach ($dbs as $db) { + $containersToStop[] = "{$db->name}-{$this->uuid}"; + } + return $containersToStop; } - public function stopContainers(array $containerNames, $server, int $timeout = 600) + public function stopContainers(array $containerNames, $server, int $timeout = 300) { $processes = []; foreach ($containerNames as $containerName) { - $processes[$containerName] = $this->stopContainer($containerName, $server, $timeout); + $processes[$containerName] = $this->stopContainer($containerName, $timeout); } $startTime = time(); @@ -142,7 +147,7 @@ class Service extends BaseModel $finishedProcesses = array_filter($processes, function ($process) { return !$process->running(); }); - foreach ($finishedProcesses as $containerName => $process) { + foreach (array_keys($finishedProcesses) as $containerName) { unset($processes[$containerName]); $this->removeContainer($containerName, $server); } @@ -156,7 +161,7 @@ class Service extends BaseModel } } - public function stopContainer(string $containerName, $server, int $timeout): InvokedProcess + public function stopContainer(string $containerName, int $timeout): InvokedProcess { return Process::timeout($timeout)->start("docker stop --time=$timeout $containerName"); } From c566152f3777a53e4e86dd7713a08599e889f3a5 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 9 Aug 2024 20:28:57 +0200 Subject: [PATCH 044/863] improve graceful_shutdown_container --- app/Jobs/ApplicationDeploymentJob.php | 45 ++++++++++++++++++++------- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php index 473cbc679..42c1ba43c 100644 --- a/app/Jobs/ApplicationDeploymentJob.php +++ b/app/Jobs/ApplicationDeploymentJob.php @@ -28,6 +28,7 @@ use Illuminate\Queue\SerializesModels; use Illuminate\Support\Collection; use Illuminate\Support\Sleep; use Illuminate\Support\Str; +use Illuminate\Support\Facades\Process; use RuntimeException; use Symfony\Component\Yaml\Yaml; use Throwable; @@ -894,7 +895,8 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue $envs->push("COOLIFY_FQDN={$this->application->fqdn}"); } if ($this->application->environment_variables->where('key', 'COOLIFY_URL')->isEmpty()) { - $url = str($this->application->fqdn)->replace('http://', '')->replace('https://', ''); + $url = str_replace('http://', '', $this->application->fqdn); + $url = str_replace('https://', '', $url); $envs->push("COOLIFY_URL={$url}"); } if ($this->application->environment_variables->where('key', 'COOLIFY_BRANCH')->isEmpty()) { @@ -2027,24 +2029,43 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf"); $this->application_deployment_queue->addLogEntry('Building docker image completed.'); } - /** - * @param int $timeout in seconds - */ - private function graceful_shutdown_container(string $containerName, int $timeout = 30) + private function graceful_shutdown_container(string $containerName, int $timeout = 300) { try { - $this->execute_remote_command( - ["docker stop --time=$timeout $containerName", 'hidden' => true, 'ignore_errors' => true], - ["docker rm $containerName", 'hidden' => true, 'ignore_errors' => true] - ); + $process = Process::timeout($timeout)->start("docker stop --time=$timeout $containerName"); + + $startTime = time(); + while ($process->running()) { + if (time() - $startTime >= $timeout) { + $this->execute_remote_command( + ["docker kill $containerName", 'hidden' => true, 'ignore_errors' => true] + ); + break; + } + usleep(100000); + } + + $isRunning = $this->execute_remote_command( + ["docker inspect -f '{{.State.Running}}' $containerName", 'hidden' => true, 'ignore_errors' => true] + ) === 'true'; + + if ($isRunning) { + $this->execute_remote_command( + ["docker kill $containerName", 'hidden' => true, 'ignore_errors' => true] + ); + } } catch (\Exception $error) { - // report error if needed + $this->application_deployment_queue->addLogEntry("Error stopping container $containerName: " . $error->getMessage(), 'stderr'); } + $this->remove_container($containerName); + } + + private function remove_container(string $containerName) + { $this->execute_remote_command( ["docker rm -f $containerName", 'hidden' => true, 'ignore_errors' => true] ); - } private function stop_running_container(bool $force = false) @@ -2057,7 +2078,7 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf"); $containers = getCurrentApplicationContainerStatus($this->server, $this->application->id, $this->pull_request_id); if ($this->pull_request_id === 0) { $containers = $containers->filter(function ($container) { - return data_get($container, 'Names') !== $this->container_name && data_get($container, 'Names') !== $this->container_name.'-pr-'.$this->pull_request_id; + return data_get($container, 'Names') !== $this->container_name && data_get($container, 'Names') !== $this->container_name . '-pr-' . $this->pull_request_id; }); } $containers->each(function ($container) { From 16a5c601e3f93d8a8fc43672958299f6bacbcd7a Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 9 Aug 2024 22:15:45 +0200 Subject: [PATCH 045/863] graceful db stop and db deletion fixes --- app/Actions/Database/StopDatabase.php | 50 ++++++++++++++++++++++++--- app/Actions/Service/StopService.php | 2 +- app/Jobs/DeleteResourceJob.php | 16 ++------- 3 files changed, 49 insertions(+), 19 deletions(-) diff --git a/app/Actions/Database/StopDatabase.php b/app/Actions/Database/StopDatabase.php index d562ec56f..29ce794cf 100644 --- a/app/Actions/Database/StopDatabase.php +++ b/app/Actions/Database/StopDatabase.php @@ -10,25 +10,65 @@ use App\Models\StandaloneMongodb; use App\Models\StandaloneMysql; use App\Models\StandalonePostgresql; use App\Models\StandaloneRedis; +use Illuminate\Support\Facades\Process; use Lorisleiva\Actions\Concerns\AsAction; +use App\Actions\Server\CleanupDocker; class StopDatabase { use AsAction; - public function handle(StandaloneRedis|StandalonePostgresql|StandaloneMongodb|StandaloneMysql|StandaloneMariadb|StandaloneKeydb|StandaloneDragonfly|StandaloneClickhouse $database) + public function handle(StandaloneRedis|StandalonePostgresql|StandaloneMongodb|StandaloneMysql|StandaloneMariadb|StandaloneKeydb|StandaloneDragonfly|StandaloneClickhouse $database, bool $isDeleteOperation = false) { $server = $database->destination->server; - if (! $server->isFunctional()) { + if (!$server->isFunctional()) { return 'Server is not functional'; } - instant_remote_process(command: ["docker stop --time=30 $database->uuid"], server: $server, throwError: false); - instant_remote_process(command: ["docker rm $database->uuid"], server: $server, throwError: false); - instant_remote_process(command: ["docker rm -f $database->uuid"], server: $server, throwError: false); + $this->stopContainer($database, $database->uuid, 300); + if (!$isDeleteOperation) { + $this->deleteConnectedNetworks($database->uuid, $server); //Probably not needed as DBs do not have a network normally + CleanupDocker::run($server, true); + } if ($database->is_public) { StopDatabaseProxy::run($database); } + + return 'Database stopped successfully'; + } + + private function stopContainer($database, string $containerName, int $timeout = 300): void + { + $server = $database->destination->server; + + $process = Process::timeout($timeout)->start("docker stop --time=$timeout $containerName"); + + $startTime = time(); + while ($process->running()) { + if (time() - $startTime >= $timeout) { + $this->forceStopContainer($containerName, $server); + break; + } + usleep(100000); + } + + $this->removeContainer($containerName, $server); + } + + private function forceStopContainer(string $containerName, $server): void + { + instant_remote_process(command: ["docker kill $containerName"], server: $server, throwError: false); + } + + private function removeContainer(string $containerName, $server): void + { + instant_remote_process(command: ["docker rm -f $containerName"], server: $server, throwError: false); + } + + private function deleteConnectedNetworks($uuid, $server) + { + instant_remote_process(["docker network disconnect {$uuid} coolify-proxy"], $server, false); + instant_remote_process(["docker network rm {$uuid}"], $server, false); } } diff --git a/app/Actions/Service/StopService.php b/app/Actions/Service/StopService.php index 85c61dc83..6b348f830 100644 --- a/app/Actions/Service/StopService.php +++ b/app/Actions/Service/StopService.php @@ -31,4 +31,4 @@ class StopService return $e->getMessage(); } } -} \ No newline at end of file +} diff --git a/app/Jobs/DeleteResourceJob.php b/app/Jobs/DeleteResourceJob.php index 6e102266a..1f4e835e9 100644 --- a/app/Jobs/DeleteResourceJob.php +++ b/app/Jobs/DeleteResourceJob.php @@ -56,17 +56,7 @@ class DeleteResourceJob implements ShouldBeEncrypted, ShouldQueue case 'standalone-dragonfly': case 'standalone-clickhouse': $persistentStorages = $this->resource?->persistentStorages()?->get(); - StopDatabase::run($this->resource); - // TODO - // DBs do not have a network normally? - //if ($this->deleteConnectedNetworks) { - // $this->resource?->delete_connected_networks($this->resource->uuid); - // } - // } - // $server = data_get($this->resource, 'server'); - // if ($this->deleteImages && $server) { - // CleanupDocker::run($server, true); - // } + StopDatabase::run($this->resource, true); break; case 'service': StopService::run($this->resource, true); @@ -80,10 +70,10 @@ class DeleteResourceJob implements ShouldBeEncrypted, ShouldQueue if ($this->deleteConfigurations) { $this->resource?->delete_configurations(); } - + $server = data_get($this->resource, 'server'); if ($this->deleteImages && $server) { - CleanupDocker::run($server, true); + CleanupDocker::run($server, true); //this is run for DBs but it does not work for DBs } if ($this->deleteConnectedNetworks) { From 7d1179e7c89bf38d5607c8f52ff1b6eb559e6d70 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 9 Aug 2024 22:25:39 +0200 Subject: [PATCH 046/863] fix cleanup images for databases --- app/Jobs/DeleteResourceJob.php | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/app/Jobs/DeleteResourceJob.php b/app/Jobs/DeleteResourceJob.php index 1f4e835e9..b0983bc47 100644 --- a/app/Jobs/DeleteResourceJob.php +++ b/app/Jobs/DeleteResourceJob.php @@ -69,11 +69,21 @@ class DeleteResourceJob implements ShouldBeEncrypted, ShouldQueue } if ($this->deleteConfigurations) { $this->resource?->delete_configurations(); + ray('Iam am running now, Configurations should disapear right?'); } - $server = data_get($this->resource, 'server'); - if ($this->deleteImages && $server) { - CleanupDocker::run($server, true); //this is run for DBs but it does not work for DBs + $isDatabase = $this->resource instanceof StandalonePostgresql + || $this->resource instanceof StandaloneRedis + || $this->resource instanceof StandaloneMongodb + || $this->resource instanceof StandaloneMysql + || $this->resource instanceof StandaloneMariadb + || $this->resource instanceof StandaloneKeydb + || $this->resource instanceof StandaloneDragonfly + || $this->resource instanceof StandaloneClickhouse; + $server = data_get($this->resource, 'server') ?? data_get($this->resource, 'destination.server'); + if (($this->deleteImages || $isDatabase) && $server) { + CleanupDocker::run($server, true); + ray('I am running now, images should disappear right?'); } if ($this->deleteConnectedNetworks) { From 840e225aa86befa895a41a789106fe317e85d66d Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 9 Aug 2024 22:43:18 +0200 Subject: [PATCH 047/863] formatting and waring text --- app/Jobs/DeleteResourceJob.php | 4 +- app/Models/ServiceDatabase.php | 4 +- .../project/database/heading.blade.php | 128 ++++++++---------- 3 files changed, 63 insertions(+), 73 deletions(-) diff --git a/app/Jobs/DeleteResourceJob.php b/app/Jobs/DeleteResourceJob.php index b0983bc47..b8a8756cb 100644 --- a/app/Jobs/DeleteResourceJob.php +++ b/app/Jobs/DeleteResourceJob.php @@ -69,9 +69,8 @@ class DeleteResourceJob implements ShouldBeEncrypted, ShouldQueue } if ($this->deleteConfigurations) { $this->resource?->delete_configurations(); - ray('Iam am running now, Configurations should disapear right?'); } - + $isDatabase = $this->resource instanceof StandalonePostgresql || $this->resource instanceof StandaloneRedis || $this->resource instanceof StandaloneMongodb @@ -83,7 +82,6 @@ class DeleteResourceJob implements ShouldBeEncrypted, ShouldQueue $server = data_get($this->resource, 'server') ?? data_get($this->resource, 'destination.server'); if (($this->deleteImages || $isDatabase) && $server) { CleanupDocker::run($server, true); - ray('I am running now, images should disappear right?'); } if ($this->deleteConnectedNetworks) { diff --git a/app/Models/ServiceDatabase.php b/app/Models/ServiceDatabase.php index 4a749913e..7bbcb4f4e 100644 --- a/app/Models/ServiceDatabase.php +++ b/app/Models/ServiceDatabase.php @@ -21,7 +21,7 @@ class ServiceDatabase extends BaseModel public function restart() { - $container_id = $this->name.'-'.$this->service->uuid; + $container_id = $this->name . '-' . $this->service->uuid; remote_process(["docker restart {$container_id}"], $this->service->server); } @@ -78,7 +78,7 @@ class ServiceDatabase extends BaseModel public function workdir() { - return service_configuration_dir()."/{$this->service->uuid}"; + return service_configuration_dir() . "/{$this->service->uuid}"; } public function service() diff --git a/resources/views/livewire/project/database/heading.blade.php b/resources/views/livewire/project/database/heading.blade.php index cee1f0520..73824421d 100644 --- a/resources/views/livewire/project/database/heading.blade.php +++ b/resources/views/livewire/project/database/heading.blade.php @@ -7,88 +7,80 @@ - + \ No newline at end of file From b5360e5e7518b3f804301d255f87fe7958eec23e Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 9 Aug 2024 23:12:30 +0200 Subject: [PATCH 048/863] improve CleanupDocker.php --- app/Actions/Server/CleanupDocker.php | 35 ++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/app/Actions/Server/CleanupDocker.php b/app/Actions/Server/CleanupDocker.php index 0009e001d..82515ab6b 100644 --- a/app/Actions/Server/CleanupDocker.php +++ b/app/Actions/Server/CleanupDocker.php @@ -11,15 +11,36 @@ class CleanupDocker public function handle(Server $server, bool $force = true) { - // cleanup docker images, containers, and builder caches + $commonCommands = [ + 'docker container prune -f --filter "label=coolify.managed=true"', + 'docker image prune -f', + 'docker builder prune -f', + 'docker network prune -f', + ]; + + $forceCommands = [ + 'docker container rm $(docker container ls -aq --filter status=exited --filter status=created)', + 'docker image prune -af', + 'docker builder prune -af', + 'docker system prune -af', + 'docker network prune -f', + ]; + + $additionalCommands = [ + 'docker rmi $(docker images -f "dangling=true" -q)', + 'docker network rm $(docker network ls -q -f "unused=true")', + 'docker system prune -f', + ]; + if ($force) { - instant_remote_process(['docker image prune -af'], $server, false); - instant_remote_process(['docker container prune -f --filter "label=coolify.managed=true"'], $server, false); - instant_remote_process(['docker builder prune -af'], $server, false); + $commands = array_merge($forceCommands, $commonCommands, $additionalCommands); + $commands[] = 'docker rm $(docker ps -a -q --filter status=exited --filter status=created)'; } else { - instant_remote_process(['docker image prune -f'], $server, false); - instant_remote_process(['docker container prune -f --filter "label=coolify.managed=true"'], $server, false); - instant_remote_process(['docker builder prune -f'], $server, false); + $commands = array_merge($commonCommands, $additionalCommands); + } + + foreach ($commands as $command) { + instant_remote_process([$command], $server, false); } } } From 5b54dc8792f884e28a7a5b7606086fb880c5cf77 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 9 Aug 2024 23:25:57 +0200 Subject: [PATCH 049/863] Revert "improve CleanupDocker.php" This reverts commit b5360e5e7518b3f804301d255f87fe7958eec23e. --- app/Actions/Server/CleanupDocker.php | 35 ++++++---------------------- 1 file changed, 7 insertions(+), 28 deletions(-) diff --git a/app/Actions/Server/CleanupDocker.php b/app/Actions/Server/CleanupDocker.php index 82515ab6b..0009e001d 100644 --- a/app/Actions/Server/CleanupDocker.php +++ b/app/Actions/Server/CleanupDocker.php @@ -11,36 +11,15 @@ class CleanupDocker public function handle(Server $server, bool $force = true) { - $commonCommands = [ - 'docker container prune -f --filter "label=coolify.managed=true"', - 'docker image prune -f', - 'docker builder prune -f', - 'docker network prune -f', - ]; - - $forceCommands = [ - 'docker container rm $(docker container ls -aq --filter status=exited --filter status=created)', - 'docker image prune -af', - 'docker builder prune -af', - 'docker system prune -af', - 'docker network prune -f', - ]; - - $additionalCommands = [ - 'docker rmi $(docker images -f "dangling=true" -q)', - 'docker network rm $(docker network ls -q -f "unused=true")', - 'docker system prune -f', - ]; - + // cleanup docker images, containers, and builder caches if ($force) { - $commands = array_merge($forceCommands, $commonCommands, $additionalCommands); - $commands[] = 'docker rm $(docker ps -a -q --filter status=exited --filter status=created)'; + instant_remote_process(['docker image prune -af'], $server, false); + instant_remote_process(['docker container prune -f --filter "label=coolify.managed=true"'], $server, false); + instant_remote_process(['docker builder prune -af'], $server, false); } else { - $commands = array_merge($commonCommands, $additionalCommands); - } - - foreach ($commands as $command) { - instant_remote_process([$command], $server, false); + instant_remote_process(['docker image prune -f'], $server, false); + instant_remote_process(['docker container prune -f --filter "label=coolify.managed=true"'], $server, false); + instant_remote_process(['docker builder prune -f'], $server, false); } } } From f080a4bf30ffc4a856a77bb2c96bc1f2bf0cca43 Mon Sep 17 00:00:00 2001 From: Telokis <6382729+Telokis@users.noreply.github.com> Date: Sun, 11 Aug 2024 15:11:52 +0200 Subject: [PATCH 050/863] Improve healthcheck --- templates/compose/organizr.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/templates/compose/organizr.yaml b/templates/compose/organizr.yaml index df95730c4..658e29c65 100644 --- a/templates/compose/organizr.yaml +++ b/templates/compose/organizr.yaml @@ -14,7 +14,7 @@ services: volumes: - organizr-data:/config healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:80"] - interval: 2s - timeout: 10s - retries: 30 + test: ["CMD-SHELL", "curl -sf http://localhost:80 || exit 1"] + interval: 10s + timeout: 1s + retries: 3 From 53abea63f7a4ec5854ad3e9bdf96a8966bbc7386 Mon Sep 17 00:00:00 2001 From: Matt <63170914+matas0@users.noreply.github.com> Date: Tue, 13 Aug 2024 23:35:46 +0400 Subject: [PATCH 051/863] feat: Dify template --- templates/compose/dify.yaml | 645 ++++++++++++++++++++++++++++++++++++ 1 file changed, 645 insertions(+) create mode 100644 templates/compose/dify.yaml diff --git a/templates/compose/dify.yaml b/templates/compose/dify.yaml new file mode 100644 index 000000000..350f93198 --- /dev/null +++ b/templates/compose/dify.yaml @@ -0,0 +1,645 @@ +# documentation: https://docs.dify.ai +# slogan: Dify is an open-source LLM app development platform. Dify's intuitive interface combines AI workflow, RAG pipeline, agent capabilities, model management, observability features and more, letting you quickly go from prototype to production. +# tags: ai, weaviate, openai, gpt, llm, lmops, dify, redis, postgres, qdrant, RAG, agent +# logo: svgs/dify.png +# port: 80 + + +x-shared-env: &shared-api-worker-env + LOG_LEVEL: ${LOG_LEVEL:-INFO} + DEBUG: ${DEBUG:-false} + FLASK_DEBUG: ${FLASK_DEBUG:-false} + CONSOLE_WEB_URL: ${CONSOLE_WEB_URL:-} + CONSOLE_API_URL: ${CONSOLE_API_URL:-} + SERVICE_API_URL: ${SERVICE_API_URL} + APP_WEB_URL: ${APP_WEB_URL:-} + CHECK_UPDATE_URL: ${CHECK_UPDATE_URL:-https://updates.dify.ai} + OPENAI_API_BASE: ${OPENAI_API_BASE:-https://api.openai.com/v1} + FILES_URL: ${FILES_URL:-} + FILES_ACCESS_TIMEOUT: ${FILES_ACCESS_TIMEOUT:-300} + APP_MAX_ACTIVE_REQUESTS: ${APP_MAX_ACTIVE_REQUESTS:-0} + MIGRATION_ENABLED: ${MIGRATION_ENABLED:-true} + DEPLOY_ENV: ${DEPLOY_ENV:-PRODUCTION} + DIFY_BIND_ADDRESS: ${DIFY_BIND_ADDRESS:-0.0.0.0} + DIFY_PORT: ${DIFY_PORT:-5001} + SERVER_WORKER_AMOUNT: ${SERVER_WORKER_AMOUNT:-} + SERVER_WORKER_CLASS: ${SERVER_WORKER_CLASS:-} + CELERY_WORKER_CLASS: ${CELERY_WORKER_CLASS:-} + GUNICORN_TIMEOUT: ${GUNICORN_TIMEOUT:-360} + CELERY_WORKER_AMOUNT: ${CELERY_WORKER_AMOUNT:-} + CELERY_AUTO_SCALE: ${CELERY_AUTO_SCALE:-false} + CELERY_MAX_WORKERS: ${CELERY_MAX_WORKERS:-} + CELERY_MIN_WORKERS: ${CELERY_MIN_WORKERS:-} + API_TOOL_DEFAULT_CONNECT_TIMEOUT: ${API_TOOL_DEFAULT_CONNECT_TIMEOUT:-10} + API_TOOL_DEFAULT_READ_TIMEOUT: ${API_TOOL_DEFAULT_READ_TIMEOUT:-60} + DB_USERNAME: ${DB_USERNAME:-postgres} + DB_PASSWORD: ${DB_PASSWORD:-difyai123456} + DB_HOST: ${DB_HOST:-db} + DB_PORT: ${DB_PORT:-5432} + DB_DATABASE: ${DB_DATABASE:-dify} + SQLALCHEMY_POOL_SIZE: ${SQLALCHEMY_POOL_SIZE:-30} + SQLALCHEMY_POOL_RECYCLE: ${SQLALCHEMY_POOL_RECYCLE:-3600} + SQLALCHEMY_ECHO: ${SQLALCHEMY_ECHO:-false} + POSTGRES_MAX_CONNECTIONS: ${POSTGRES_MAX_CONNECTIONS:-100} + POSTGRES_SHARED_BUFFERS: ${POSTGRES_SHARED_BUFFERS:-128MB} + POSTGRES_WORK_MEM: ${POSTGRES_WORK_MEM:-4MB} + POSTGRES_MAINTENANCE_WORK_MEM: ${POSTGRES_MAINTENANCE_WORK_MEM:-64MB} + POSTGRES_EFFECTIVE_CACHE_SIZE: ${POSTGRES_EFFECTIVE_CACHE_SIZE:-4096MB} + REDIS_HOST: ${REDIS_HOST:-redis} + REDIS_PORT: ${REDIS_PORT:-6379} + REDIS_USERNAME: ${REDIS_USERNAME:-} + REDIS_PASSWORD: $SERVICE_PASSWORD_REDIS + REDIS_USE_SSL: ${REDIS_USE_SSL:-false} + REDIS_DB: 0 + CELERY_BROKER_URL: ${CELERY_BROKER_URL:-redis://:$SERVICE_PASSWORD_REDIS@redis:6379/1} + BROKER_USE_SSL: ${BROKER_USE_SSL:-false} + WEB_API_CORS_ALLOW_ORIGINS: ${WEB_API_CORS_ALLOW_ORIGINS:-*} + CONSOLE_CORS_ALLOW_ORIGINS: ${CONSOLE_CORS_ALLOW_ORIGINS:-*} + STORAGE_TYPE: ${STORAGE_TYPE:-local} + STORAGE_LOCAL_PATH: storage + S3_USE_AWS_MANAGED_IAM: ${S3_USE_AWS_MANAGED_IAM:-false} + S3_ENDPOINT: ${S3_ENDPOINT:-} + S3_BUCKET_NAME: ${S3_BUCKET_NAME:-} + S3_ACCESS_KEY: ${S3_ACCESS_KEY:-} + S3_SECRET_KEY: ${S3_SECRET_KEY:-} + S3_REGION: ${S3_REGION:-us-east-1} + AZURE_BLOB_ACCOUNT_NAME: ${AZURE_BLOB_ACCOUNT_NAME:-} + AZURE_BLOB_ACCOUNT_KEY: ${AZURE_BLOB_ACCOUNT_KEY:-} + AZURE_BLOB_CONTAINER_NAME: ${AZURE_BLOB_CONTAINER_NAME:-} + AZURE_BLOB_ACCOUNT_URL: ${AZURE_BLOB_ACCOUNT_URL:-} + GOOGLE_STORAGE_BUCKET_NAME: ${GOOGLE_STORAGE_BUCKET_NAME:-} + GOOGLE_STORAGE_SERVICE_ACCOUNT_JSON_BASE64: ${GOOGLE_STORAGE_SERVICE_ACCOUNT_JSON_BASE64:-} + ALIYUN_OSS_BUCKET_NAME: ${ALIYUN_OSS_BUCKET_NAME:-} + ALIYUN_OSS_ACCESS_KEY: ${ALIYUN_OSS_ACCESS_KEY:-} + ALIYUN_OSS_SECRET_KEY: ${ALIYUN_OSS_SECRET_KEY:-} + ALIYUN_OSS_ENDPOINT: ${ALIYUN_OSS_ENDPOINT:-} + ALIYUN_OSS_REGION: ${ALIYUN_OSS_REGION:-} + ALIYUN_OSS_AUTH_VERSION: ${ALIYUN_OSS_AUTH_VERSION:-v4} + TENCENT_COS_BUCKET_NAME: ${TENCENT_COS_BUCKET_NAME:-} + TENCENT_COS_SECRET_KEY: ${TENCENT_COS_SECRET_KEY:-} + TENCENT_COS_SECRET_ID: ${TENCENT_COS_SECRET_ID:-} + TENCENT_COS_REGION: ${TENCENT_COS_REGION:-} + TENCENT_COS_SCHEME: ${TENCENT_COS_SCHEME:-} + OCI_ENDPOINT: ${OCI_ENDPOINT:-} + OCI_BUCKET_NAME: ${OCI_BUCKET_NAME:-} + OCI_ACCESS_KEY: ${OCI_ACCESS_KEY:-} + OCI_SECRET_KEY: ${OCI_SECRET_KEY:-} + OCI_REGION: ${OCI_REGION:-} + VECTOR_STORE: ${VECTOR_STORE:-weaviate} + WEAVIATE_ENDPOINT: ${WEAVIATE_ENDPOINT:-http://weaviate:8080} + WEAVIATE_API_KEY: $SERVICE_PASSWORD_WEAVIATE + RELYT_HOST: ${RELYT_HOST:-db} + RELYT_PORT: ${RELYT_PORT:-5432} + RELYT_USER: $SERVICE_USER_RELYT + RELYT_PASSWORD: $SERVICE_PASSWORD_RELYT + RELYT_DATABASE: ${RELYT_DATABASE:-postgres} + TIDB_VECTOR_HOST: ${TIDB_VECTOR_HOST:-tidb} + TIDB_VECTOR_PORT: ${TIDB_VECTOR_PORT:-4000} + TIDB_VECTOR_USER: $SERVICE_USER_TIDB + TIDB_VECTOR_PASSWORD: $SERVICE_PASSWORD_TIDB + TIDB_VECTOR_DATABASE: ${TIDB_VECTOR_DATABASE:-dify} + # AnalyticDB configuration + ANALYTICDB_KEY_ID: ${ANALYTICDB_KEY_ID:-} + ANALYTICDB_KEY_SECRET: ${ANALYTICDB_KEY_SECRET:-} + ANALYTICDB_REGION_ID: ${ANALYTICDB_REGION_ID:-} + ANALYTICDB_INSTANCE_ID: ${ANALYTICDB_INSTANCE_ID:-} + ANALYTICDB_ACCOUNT: ${ANALYTICDB_ACCOUNT:-} + ANALYTICDB_PASSWORD: ${ANALYTICDB_PASSWORD:-} + ANALYTICDB_NAMESPACE: ${ANALYTICDB_NAMESPACE:-dify} + ANALYTICDB_NAMESPACE_PASSWORD: ${ANALYTICDB_NAMESPACE_PASSWORD:-} + TENCENT_VECTOR_DB_URL: ${TENCENT_VECTOR_DB_URL:-http://127.0.0.1} + TENCENT_VECTOR_DB_API_KEY: ${TENCENT_VECTOR_DB_API_KEY:-dify} + TENCENT_VECTOR_DB_TIMEOUT: ${TENCENT_VECTOR_DB_TIMEOUT:-30} + TENCENT_VECTOR_DB_USERNAME: ${TENCENT_VECTOR_DB_USERNAME:-dify} + TENCENT_VECTOR_DB_DATABASE: ${TENCENT_VECTOR_DB_DATABASE:-dify} + TENCENT_VECTOR_DB_SHARD: ${TENCENT_VECTOR_DB_SHARD:-1} + TENCENT_VECTOR_DB_REPLICAS: ${TENCENT_VECTOR_DB_REPLICAS:-2} + UPLOAD_FILE_SIZE_LIMIT: ${UPLOAD_FILE_SIZE_LIMIT:-15} + UPLOAD_FILE_BATCH_LIMIT: ${UPLOAD_FILE_BATCH_LIMIT:-5} + ETL_TYPE: ${ETL_TYPE:-dify} + MULTIMODAL_SEND_IMAGE_FORMAT: ${MULTIMODAL_SEND_IMAGE_FORMAT:-base64} + UPLOAD_IMAGE_FILE_SIZE_LIMIT: ${UPLOAD_IMAGE_FILE_SIZE_LIMIT:-10} + SENTRY_DSN: ${API_SENTRY_DSN:-} + SENTRY_TRACES_SAMPLE_RATE: ${API_SENTRY_TRACES_SAMPLE_RATE:-1.0} + SENTRY_PROFILES_SAMPLE_RATE: ${API_SENTRY_PROFILES_SAMPLE_RATE:-1.0} + NOTION_INTEGRATION_TYPE: ${NOTION_INTEGRATION_TYPE:-public} + NOTION_CLIENT_SECRET: ${NOTION_CLIENT_SECRET:-} + NOTION_CLIENT_ID: ${NOTION_CLIENT_ID:-} + NOTION_INTERNAL_SECRET: ${NOTION_INTERNAL_SECRET:-} + MAIL_TYPE: ${MAIL_TYPE:-resend} + MAIL_DEFAULT_SEND_FROM: ${MAIL_DEFAULT_SEND_FROM:-} + SMTP_SERVER: ${SMTP_SERVER:-} + SMTP_PORT: ${SMTP_PORT:-465} + SMTP_USERNAME: ${SMTP_USERNAME:-} + SMTP_PASSWORD: ${SMTP_PASSWORD:-} + SMTP_USE_TLS: ${SMTP_USE_TLS:-true} + SMTP_OPPORTUNISTIC_TLS: ${SMTP_OPPORTUNISTIC_TLS:-false} + RESEND_API_KEY: ${RESEND_API_KEY:-your-resend-api-key} + RESEND_API_URL: https://api.resend.com + INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH: ${INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH:-1000} + INVITE_EXPIRY_HOURS: ${INVITE_EXPIRY_HOURS:-72} + RESET_PASSWORD_TOKEN_EXPIRY_HOURS: ${RESET_PASSWORD_TOKEN_EXPIRY_HOURS:-24} + CODE_EXECUTION_ENDPOINT: ${CODE_EXECUTION_ENDPOINT:-http://sandbox:8194} + CODE_EXECUTION_API_KEY: ${SANDBOX_API_KEY:-dify-sandbox} + CODE_MAX_NUMBER: ${CODE_MAX_NUMBER:-9223372036854775807} + CODE_MIN_NUMBER: ${CODE_MIN_NUMBER:--9223372036854775808} + CODE_MAX_STRING_LENGTH: ${CODE_MAX_STRING_LENGTH:-80000} + TEMPLATE_TRANSFORM_MAX_LENGTH: ${TEMPLATE_TRANSFORM_MAX_LENGTH:-80000} + CODE_MAX_STRING_ARRAY_LENGTH: ${CODE_MAX_STRING_ARRAY_LENGTH:-30} + CODE_MAX_OBJECT_ARRAY_LENGTH: ${CODE_MAX_OBJECT_ARRAY_LENGTH:-30} + CODE_MAX_NUMBER_ARRAY_LENGTH: ${CODE_MAX_NUMBER_ARRAY_LENGTH:-1000} + SSRF_PROXY_HTTP_URL: ${SSRF_PROXY_HTTP_URL:-http://ssrf_proxy:3128} + SSRF_PROXY_HTTPS_URL: ${SSRF_PROXY_HTTPS_URL:-http://ssrf_proxy:3128} + +services: + # API service + api: + image: langgenius/dify-api:0.6.16 + restart: always + environment: + SECRET_KEY: $SERVICE_PASSWORD_64_SECRETKEY + INIT_PASSWORD: $SERVICE_USER_INITPASSWORD + # Use the shared environment variables. + <<: *shared-api-worker-env + # Startup mode, 'api' starts the API server. + MODE: api + depends_on: + - db + - redis + volumes: + # Mount the storage directory to the container, for storing user files. + - './volumes/app/storage:/app/api/storage' + networks: + - ssrf_proxy_network + - default + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:5001/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + + # worker service + # The Celery worker for processing the queue. + worker: + image: langgenius/dify-api:0.6.16 + restart: always + environment: + # Use the shared environment variables. + <<: *shared-api-worker-env + # Startup mode, 'worker' starts the Celery worker for processing the queue. + MODE: worker + depends_on: + - db + - redis + volumes: + # Mount the storage directory to the container, for storing user files. + - './volumes/app/storage:/app/api/storage' + networks: + - ssrf_proxy_network + - default + healthcheck: + test: ["CMD-SHELL", "celery -A app.celery_app inspect ping -d celery@$HOSTNAME"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + + # Frontend web application. + web: + image: langgenius/dify-web:0.6.16 + restart: always + environment: + CONSOLE_API_URL: ${CONSOLE_API_URL:-} + APP_API_URL: ${APP_API_URL:-} + SENTRY_DSN: ${WEB_SENTRY_DSN:-} + NEXT_TELEMETRY_DISABLED: ${NEXT_TELEMETRY_DISABLED:-0} + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:3000"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + + # The postgres database. + db: + image: postgres:15-alpine + restart: always + environment: + PGUSER: ${PGUSER:-postgres} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-difyai123456} + POSTGRES_DB: ${POSTGRES_DB:-dify} + PGDATA: ${PGDATA:-/var/lib/postgresql/data/pgdata} + command: > + postgres -c 'max_connections=${POSTGRES_MAX_CONNECTIONS:-100}' + -c 'shared_buffers=${POSTGRES_SHARED_BUFFERS:-128MB}' + -c 'work_mem=${POSTGRES_WORK_MEM:-4MB}' + -c 'maintenance_work_mem=${POSTGRES_MAINTENANCE_WORK_MEM:-64MB}' + -c 'effective_cache_size=${POSTGRES_EFFECTIVE_CACHE_SIZE:-4096MB}' + volumes: + - './volumes/db/data:/var/lib/postgresql/data' + healthcheck: + test: [ "CMD", "pg_isready" ] + interval: 1s + timeout: 3s + retries: 30 + + # The redis cache. + redis: + image: redis:6-alpine + restart: always + volumes: + # Mount the redis data directory to the container. + - './volumes/redis/data:/data' + # Set the redis password when startup redis server. + command: redis-server --requirepass $SERVICE_PASSWORD_REDIS + healthcheck: + test: [ "CMD", "redis-cli", "-a", "$SERVICE_PASSWORD_REDIS", "ping" ] + + # The DifySandbox + sandbox: + image: langgenius/dify-sandbox:0.2.1 + restart: always + environment: + # The DifySandbox configurations + # Make sure you are changing this key for your deployment with a strong key. + # You can generate a strong key using `openssl rand -base64 42`. + API_KEY: ${SANDBOX_API_KEY:-dify-sandbox} + GIN_MODE: ${SANDBOX_GIN_MODE:-release} + WORKER_TIMEOUT: ${SANDBOX_WORKER_TIMEOUT:-15} + ENABLE_NETWORK: ${SANDBOX_ENABLE_NETWORK:-true} + HTTP_PROXY: ${SANDBOX_HTTP_PROXY:-http://ssrf_proxy:3128} + HTTPS_PROXY: ${SANDBOX_HTTPS_PROXY:-http://ssrf_proxy:3128} + SANDBOX_PORT: ${SANDBOX_PORT:-8194} + volumes: + - './volumes/sandbox/dependencies:/dependencies' + networks: + - ssrf_proxy_network + - default + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8194/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + + # ssrf_proxy server + # for more information, please refer to + # https://docs.dify.ai/learn-more/faq/self-host-faq#id-18.-why-is-ssrf_proxy-needed + ssrf_proxy: + image: ubuntu/squid:latest + restart: always + volumes: + - type: bind + source: ./ssrf_proxy/squid.conf.template + target: /etc/squid/squid.conf.template + read_only: true + content: | + acl localnet src 0.0.0.1-0.255.255.255 # RFC 1122 "this" network (LAN) + acl localnet src 10.0.0.0/8 # RFC 1918 local private network (LAN) + acl localnet src 100.64.0.0/10 # RFC 6598 shared address space (CGN) + acl localnet src 169.254.0.0/16 # RFC 3927 link-local (directly plugged) machines + acl localnet src 172.16.0.0/12 # RFC 1918 local private network (LAN) + acl localnet src 192.168.0.0/16 # RFC 1918 local private network (LAN) + acl localnet src fc00::/7 # RFC 4193 local private network range + acl localnet src fe80::/10 # RFC 4291 link-local (directly plugged) machines + acl SSL_ports port 443 + acl Safe_ports port 80 # http + acl Safe_ports port 21 # ftp + acl Safe_ports port 443 # https + acl Safe_ports port 70 # gopher + acl Safe_ports port 210 # wais + acl Safe_ports port 1025-65535 # unregistered ports + acl Safe_ports port 280 # http-mgmt + acl Safe_ports port 488 # gss-http + acl Safe_ports port 591 # filemaker + acl Safe_ports port 777 # multiling http + acl CONNECT method CONNECT + http_access deny !Safe_ports + http_access deny CONNECT !SSL_ports + http_access allow localhost manager + http_access deny manager + http_access allow localhost + include /etc/squid/conf.d/*.conf + http_access deny all + + ################################## Proxy Server ################################ + http_port 3128 + coredump_dir ${COREDUMP_DIR} + refresh_pattern ^ftp: 1440 20% 10080 + refresh_pattern ^gopher: 1440 0% 1440 + refresh_pattern -i (/cgi-bin/|\?) 0 0% 0 + refresh_pattern \/(Packages|Sources)(|\.bz2|\.gz|\.xz)$ 0 0% 0 refresh-ims + refresh_pattern \/Release(|\.gpg)$ 0 0% 0 refresh-ims + refresh_pattern \/InRelease$ 0 0% 0 refresh-ims + refresh_pattern \/(Translation-.*)(|\.bz2|\.gz|\.xz)$ 0 0% 0 refresh-ims + refresh_pattern . 0 20% 4320 + + + # cache_dir ufs /var/spool/squid 100 16 256 + # upstream proxy, set to your own upstream proxy IP to avoid SSRF attacks + # cache_peer 172.1.1.1 parent 3128 0 no-query no-digest no-netdb-exchange default + + ################################## Reverse Proxy To Sandbox ################################ + http_port 3129 accel vhost + cache_peer ${SANDBOX_HOST} parent ${SANDBOX_PORT} 0 no-query originserver + acl src_all src all + http_access allow src_all + - type: bind + source: ./ssrf_proxy/docker-entrypoint.sh + target: /docker-entrypoint.sh + read_only: true + content: | + #!/bin/bash + + # Modified based on Squid OCI image entrypoint + + # This entrypoint aims to forward the squid logs to stdout to assist users of + # common container related tooling (e.g., kubernetes, docker-compose, etc) to + # access the service logs. + + # Moreover, it invokes the squid binary, leaving all the desired parameters to + # be provided by the "command" passed to the spawned container. If no command + # is provided by the user, the default behavior (as per the CMD statement in + # the Dockerfile) will be to use Ubuntu's default configuration [1] and run + # squid with the "-NYC" options to mimic the behavior of the Ubuntu provided + # systemd unit. + + # [1] The default configuration is changed in the Dockerfile to allow local + # network connections. See the Dockerfile for further information. + + echo "[ENTRYPOINT] re-create snakeoil self-signed certificate removed in the build process" + if [ ! -f /etc/ssl/private/ssl-cert-snakeoil.key ]; then + /usr/sbin/make-ssl-cert generate-default-snakeoil --force-overwrite > /dev/null 2>&1 + fi + + tail -F /var/log/squid/access.log 2>/dev/null & + tail -F /var/log/squid/error.log 2>/dev/null & + tail -F /var/log/squid/store.log 2>/dev/null & + tail -F /var/log/squid/cache.log 2>/dev/null & + + # Replace environment variables in the template and output to the squid.conf + echo "[ENTRYPOINT] replacing environment variables in the template" + awk '{ + while(match($0, /\${[A-Za-z_][A-Za-z_0-9]*}/)) { + var = substr($0, RSTART+2, RLENGTH-3) + val = ENVIRON[var] + $0 = substr($0, 1, RSTART-1) val substr($0, RSTART+RLENGTH) + } + print + }' /etc/squid/squid.conf.template > /etc/squid/squid.conf + + /usr/sbin/squid -Nz + echo "[ENTRYPOINT] starting squid" + /usr/sbin/squid -f /etc/squid/squid.conf -NYC 1 + - ssrf_proxy_var_log_squid:/var/log/squid + - ssrf_proxy_var_spool_squid:/var/spool/squid + entrypoint: ["/bin/sh", "/docker-entrypoint.sh"] + environment: + # pls clearly modify the squid env vars to fit your network environment. + HTTP_PORT: ${SSRF_HTTP_PORT:-3128} + COREDUMP_DIR: ${SSRF_COREDUMP_DIR:-/var/spool/squid} + REVERSE_PROXY_PORT: ${SSRF_REVERSE_PROXY_PORT:-8194} + SANDBOX_HOST: ${SSRF_SANDBOX_HOST:-sandbox} + SANDBOX_PORT: ${SANDBOX_PORT:-8194} + networks: + - ssrf_proxy_network + - default + healthcheck: + test: ["CMD", "squid", "-k", "check"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + + # The nginx reverse proxy. + # used for reverse proxying the API service and Web service. + nginx: + image: nginx:latest + restart: always + volumes: + - type: bind + source: ./nginx/nginx.conf.template + target: /etc/nginx/nginx.conf.template + read_only: true + content: | + # Please do not directly edit this file. Instead, modify the .env variables related to NGINX configuration. + + user nginx; + worker_processes ${NGINX_WORKER_PROCESSES}; + + error_log /var/log/nginx/error.log notice; + pid /var/run/nginx.pid; + + + events { + worker_connections 1024; + } + + + http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + #tcp_nopush on; + + keepalive_timeout ${NGINX_KEEPALIVE_TIMEOUT}; + + #gzip on; + client_max_body_size ${NGINX_CLIENT_MAX_BODY_SIZE}; + + include /etc/nginx/conf.d/*.conf; + } + - type: bind + source: ./nginx/proxy.conf.template + target: /etc/nginx/proxy.conf.template + read_only: true + content: | + # Please do not directly edit this file. Instead, modify the .env variables related to NGINX configuration. + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_http_version 1.1; + proxy_set_header Connection ""; + proxy_buffering off; + proxy_read_timeout ${NGINX_PROXY_READ_TIMEOUT}; + proxy_send_timeout ${NGINX_PROXY_SEND_TIMEOUT}; + - type: bind + source: ./nginx/https.conf.template + target: /etc/nginx/https.conf.template + read_only: true + content: | + # Please do not directly edit this file. Instead, modify the .env variables related to NGINX configuration. + + listen ${NGINX_SSL_PORT} ssl; + ssl_certificate ${SSL_CERTIFICATE_PATH}; + ssl_certificate_key ${SSL_CERTIFICATE_KEY_PATH}; + ssl_protocols ${NGINX_SSL_PROTOCOLS}; + ssl_prefer_server_ciphers on; + ssl_session_cache shared:SSL:10m; + ssl_session_timeout 10m; + - type: bind + source: ./nginx/docker-entrypoint.sh + target: /docker-entrypoint-mount.sh + read_only: true + content: | + #!/bin/bash + + if [ "${NGINX_HTTPS_ENABLED}" = "true" ]; then + # Check if the certificate and key files for the specified domain exist + if [ -n "${CERTBOT_DOMAIN}" ] && \ + [ -f "/etc/letsencrypt/live/${CERTBOT_DOMAIN}/${NGINX_SSL_CERT_FILENAME}" ] && \ + [ -f "/etc/letsencrypt/live/${CERTBOT_DOMAIN}/${NGINX_SSL_CERT_KEY_FILENAME}" ]; then + SSL_CERTIFICATE_PATH="/etc/letsencrypt/live/${CERTBOT_DOMAIN}/${NGINX_SSL_CERT_FILENAME}" + SSL_CERTIFICATE_KEY_PATH="/etc/letsencrypt/live/${CERTBOT_DOMAIN}/${NGINX_SSL_CERT_KEY_FILENAME}" + else + SSL_CERTIFICATE_PATH="/etc/ssl/${NGINX_SSL_CERT_FILENAME}" + SSL_CERTIFICATE_KEY_PATH="/etc/ssl/${NGINX_SSL_CERT_KEY_FILENAME}" + fi + export SSL_CERTIFICATE_PATH + export SSL_CERTIFICATE_KEY_PATH + + # set the HTTPS_CONFIG environment variable to the content of the https.conf.template + HTTPS_CONFIG=$(envsubst < /etc/nginx/https.conf.template) + export HTTPS_CONFIG + # Substitute the HTTPS_CONFIG in the default.conf.template with content from https.conf.template + envsubst '${HTTPS_CONFIG}' < /etc/nginx/conf.d/default.conf.template > /etc/nginx/conf.d/default.conf + fi + + if [ "${NGINX_ENABLE_CERTBOT_CHALLENGE}" = "true" ]; then + ACME_CHALLENGE_LOCATION='location /.well-known/acme-challenge/ { root /var/www/html; }' + else + ACME_CHALLENGE_LOCATION='' + fi + export ACME_CHALLENGE_LOCATION + + env_vars=$(printenv | cut -d= -f1 | sed 's/^/$/g' | paste -sd, -) + + envsubst "$env_vars" < /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf + envsubst "$env_vars" < /etc/nginx/proxy.conf.template > /etc/nginx/proxy.conf + + envsubst < /etc/nginx/conf.d/default.conf.template > /etc/nginx/conf.d/default.conf + + # Start Nginx using the default entrypoint + exec nginx -g 'daemon off;' + - type: bind + source: ./nginx/default.conf.template + target: /etc/nginx/conf.d/default.conf.template + read_only: true + content: | + # Please do not directly edit this file. Instead, modify the .env variables related to NGINX configuration. + + server { + listen ${NGINX_PORT}; + server_name ${NGINX_SERVER_NAME}; + + location /console/api { + proxy_pass http://api:5001; + include proxy.conf; + } + + location /api { + proxy_pass http://api:5001; + include proxy.conf; + } + + location /v1 { + proxy_pass http://api:5001; + include proxy.conf; + } + + location /files { + proxy_pass http://api:5001; + include proxy.conf; + } + + location / { + proxy_pass http://web:3000; + include proxy.conf; + } + + # placeholder for acme challenge location + ${ACME_CHALLENGE_LOCATION} + + # placeholder for https config defined in https.conf.template + ${HTTPS_CONFIG} + } + - './nginx/ssl:/etc/ssl' + - './volumes/certbot/conf/live:/etc/letsencrypt/live' + - './volumes/certbot/conf:/etc/letsencrypt' + - './volumes/certbot/www:/var/www/html' + entrypoint: [ "sh", "-c", "cp /docker-entrypoint-mount.sh /docker-entrypoint.sh && sed -i 's/\r$$//' /docker-entrypoint.sh && chmod +x /docker-entrypoint.sh && /docker-entrypoint.sh" ] + environment: + NGINX_SERVER_NAME: $SERVICE_FQDN_NGINX + NGINX_HTTPS_ENABLED: ${NGINX_HTTPS_ENABLED:-false} + NGINX_SSL_PORT: ${NGINX_SSL_PORT:-443} + NGINX_PORT: ${NGINX_PORT:-80} + # You're required to add your own SSL certificates/keys to the `./nginx/ssl` directory + # and modify the env vars below in .env if HTTPS_ENABLED is true. + NGINX_SSL_CERT_FILENAME: ${NGINX_SSL_CERT_FILENAME:-dify.crt} + NGINX_SSL_CERT_KEY_FILENAME: ${NGINX_SSL_CERT_KEY_FILENAME:-dify.key} + NGINX_SSL_PROTOCOLS: ${NGINX_SSL_PROTOCOLS:-TLSv1.1 TLSv1.2 TLSv1.3} + NGINX_WORKER_PROCESSES: ${NGINX_WORKER_PROCESSES:-auto} + NGINX_CLIENT_MAX_BODY_SIZE: ${NGINX_CLIENT_MAX_BODY_SIZE:-15M} + NGINX_KEEPALIVE_TIMEOUT: ${NGINX_KEEPALIVE_TIMEOUT:-65} + NGINX_PROXY_READ_TIMEOUT: ${NGINX_PROXY_READ_TIMEOUT:-3600s} + NGINX_PROXY_SEND_TIMEOUT: ${NGINX_PROXY_SEND_TIMEOUT:-3600s} + NGINX_ENABLE_CERTBOT_CHALLENGE: ${NGINX_ENABLE_CERTBOT_CHALLENGE:-false} + CERTBOT_DOMAIN: ${CERTBOT_DOMAIN:-} + depends_on: + - api + - web + healthcheck: + test: ["CMD", "nginx", "-t"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + + + # The Weaviate vector store. + weaviate: + image: semitechnologies/weaviate:1.19.0 + profiles: + - '' + - weaviate + restart: always + volumes: + # Mount the Weaviate data directory to the con tainer. + - ./volumes/weaviate:/var/lib/weaviate + environment: + # The Weaviate configurations + # You can refer to the [Weaviate](https://weaviate.io/developers/weaviate/config-refs/env-vars) documentation for more information. + PERSISTENCE_DATA_PATH: ${WEAVIATE_PERSISTENCE_DATA_PATH:-/var/lib/weaviate} + QUERY_DEFAULTS_LIMIT: ${WEAVIATE_QUERY_DEFAULTS_LIMIT:-25} + AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: ${WEAVIATE_AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED:-false} + DEFAULT_VECTORIZER_MODULE: ${WEAVIATE_DEFAULT_VECTORIZER_MODULE:-none} + CLUSTER_HOSTNAME: ${WEAVIATE_CLUSTER_HOSTNAME:-node1} + AUTHENTICATION_APIKEY_ENABLED: ${WEAVIATE_AUTHENTICATION_APIKEY_ENABLED:-true} + AUTHENTICATION_APIKEY_ALLOWED_KEYS: $SERVICE_PASSWORD_WEAVIATE + AUTHENTICATION_APIKEY_USERS: $SERVICE_USER_WEAVIATE + AUTHORIZATION_ADMINLIST_ENABLED: ${WEAVIATE_AUTHORIZATION_ADMINLIST_ENABLED:-true} + AUTHORIZATION_ADMINLIST_USERS: $SERVICE_USER_WEAVIATE + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8080/v1/.well-known/live"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + +networks: + # create a network between sandbox, api and ssrf_proxy, and can not access outside. + ssrf_proxy_network: + driver: bridge + internal: true + +volumes: + ssrf_proxy_var_log_squid: + ssrf_proxy_var_spool_squid: From b8cf64dd2a13c580359189f117da15de024cdf87 Mon Sep 17 00:00:00 2001 From: Matt <63170914+OhThatMatt@users.noreply.github.com> Date: Wed, 14 Aug 2024 22:39:10 +0400 Subject: [PATCH 052/863] Dify template improvements --- templates/compose/dify.yaml | 48 ++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 27 deletions(-) diff --git a/templates/compose/dify.yaml b/templates/compose/dify.yaml index 350f93198..95690b226 100644 --- a/templates/compose/dify.yaml +++ b/templates/compose/dify.yaml @@ -11,7 +11,7 @@ x-shared-env: &shared-api-worker-env FLASK_DEBUG: ${FLASK_DEBUG:-false} CONSOLE_WEB_URL: ${CONSOLE_WEB_URL:-} CONSOLE_API_URL: ${CONSOLE_API_URL:-} - SERVICE_API_URL: ${SERVICE_API_URL} + SERVICE_API_URL: APP_WEB_URL: ${APP_WEB_URL:-} CHECK_UPDATE_URL: ${CHECK_UPDATE_URL:-https://updates.dify.ai} OPENAI_API_BASE: ${OPENAI_API_BASE:-https://api.openai.com/v1} @@ -32,11 +32,11 @@ x-shared-env: &shared-api-worker-env CELERY_MIN_WORKERS: ${CELERY_MIN_WORKERS:-} API_TOOL_DEFAULT_CONNECT_TIMEOUT: ${API_TOOL_DEFAULT_CONNECT_TIMEOUT:-10} API_TOOL_DEFAULT_READ_TIMEOUT: ${API_TOOL_DEFAULT_READ_TIMEOUT:-60} - DB_USERNAME: ${DB_USERNAME:-postgres} - DB_PASSWORD: ${DB_PASSWORD:-difyai123456} + DB_USERNAME: $SERVICE_USER_POSTGRES + DB_PASSWORD: $SERVICE_PASSWORD_POSTGRES DB_HOST: ${DB_HOST:-db} DB_PORT: ${DB_PORT:-5432} - DB_DATABASE: ${DB_DATABASE:-dify} + DB_DATABASE: dify SQLALCHEMY_POOL_SIZE: ${SQLALCHEMY_POOL_SIZE:-30} SQLALCHEMY_POOL_RECYCLE: ${SQLALCHEMY_POOL_RECYCLE:-3600} SQLALCHEMY_ECHO: ${SQLALCHEMY_ECHO:-false} @@ -51,7 +51,7 @@ x-shared-env: &shared-api-worker-env REDIS_PASSWORD: $SERVICE_PASSWORD_REDIS REDIS_USE_SSL: ${REDIS_USE_SSL:-false} REDIS_DB: 0 - CELERY_BROKER_URL: ${CELERY_BROKER_URL:-redis://:$SERVICE_PASSWORD_REDIS@redis:6379/1} + CELERY_BROKER_URL: redis://:$SERVICE_PASSWORD_REDIS@redis:6379/1 BROKER_USE_SSL: ${BROKER_USE_SSL:-false} WEB_API_CORS_ALLOW_ORIGINS: ${WEB_API_CORS_ALLOW_ORIGINS:-*} CONSOLE_CORS_ALLOW_ORIGINS: ${CONSOLE_CORS_ALLOW_ORIGINS:-*} @@ -154,7 +154,7 @@ x-shared-env: &shared-api-worker-env services: # API service api: - image: langgenius/dify-api:0.6.16 + image: langgenius/dify-api:latest restart: always environment: SECRET_KEY: $SERVICE_PASSWORD_64_SECRETKEY @@ -182,7 +182,7 @@ services: # worker service # The Celery worker for processing the queue. worker: - image: langgenius/dify-api:0.6.16 + image: langgenius/dify-api:latest restart: always environment: # Use the shared environment variables. @@ -199,7 +199,7 @@ services: - ssrf_proxy_network - default healthcheck: - test: ["CMD-SHELL", "celery -A app.celery_app inspect ping -d celery@$HOSTNAME"] + test: ["CMD-SHELL", "celery inspect ping"] interval: 30s timeout: 10s retries: 3 @@ -207,7 +207,7 @@ services: # Frontend web application. web: - image: langgenius/dify-web:0.6.16 + image: langgenius/dify-web:latest restart: always environment: CONSOLE_API_URL: ${CONSOLE_API_URL:-} @@ -215,7 +215,7 @@ services: SENTRY_DSN: ${WEB_SENTRY_DSN:-} NEXT_TELEMETRY_DISABLED: ${NEXT_TELEMETRY_DISABLED:-0} healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:3000"] + test: ["CMD", "wget", "--spider", "-q", "http://web:3000"] interval: 30s timeout: 10s retries: 3 @@ -226,10 +226,10 @@ services: image: postgres:15-alpine restart: always environment: - PGUSER: ${PGUSER:-postgres} - POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-difyai123456} - POSTGRES_DB: ${POSTGRES_DB:-dify} - PGDATA: ${PGDATA:-/var/lib/postgresql/data/pgdata} + POSTGRES_USER: $SERVICE_USER_POSTGRES + POSTGRES_PASSWORD: $SERVICE_PASSWORD_POSTGRES + POSTGRES_DB: dify + PGDATA: /var/lib/postgresql/data/pgdata command: > postgres -c 'max_connections=${POSTGRES_MAX_CONNECTIONS:-100}' -c 'shared_buffers=${POSTGRES_SHARED_BUFFERS:-128MB}' @@ -239,10 +239,10 @@ services: volumes: - './volumes/db/data:/var/lib/postgresql/data' healthcheck: - test: [ "CMD", "pg_isready" ] - interval: 1s - timeout: 3s - retries: 30 + test: ["CMD", "pg_isready", "-U", "$SERVICE_USER_POSTGRES", "-d", "dify"] + interval: 10s + timeout: 5s + retries: 5 # The redis cache. redis: @@ -252,13 +252,13 @@ services: # Mount the redis data directory to the container. - './volumes/redis/data:/data' # Set the redis password when startup redis server. - command: redis-server --requirepass $SERVICE_PASSWORD_REDIS + command: redis-server --requirepass "$SERVICE_PASSWORD_REDIS" healthcheck: test: [ "CMD", "redis-cli", "-a", "$SERVICE_PASSWORD_REDIS", "ping" ] # The DifySandbox sandbox: - image: langgenius/dify-sandbox:0.2.1 + image: langgenius/dify-sandbox:latest restart: always environment: # The DifySandbox configurations @@ -276,12 +276,6 @@ services: networks: - ssrf_proxy_network - default - healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:8194/health"] - interval: 30s - timeout: 10s - retries: 3 - start_period: 40s # ssrf_proxy server # for more information, please refer to @@ -628,7 +622,7 @@ services: AUTHORIZATION_ADMINLIST_ENABLED: ${WEAVIATE_AUTHORIZATION_ADMINLIST_ENABLED:-true} AUTHORIZATION_ADMINLIST_USERS: $SERVICE_USER_WEAVIATE healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:8080/v1/.well-known/live"] + test: ["CMD", "wget", "--spider", "-q", "http://localhost:8080/v1/.well-known/live"] interval: 30s timeout: 10s retries: 3 From 6faf80fd797f0e395598dd2781c63d7f7d754834 Mon Sep 17 00:00:00 2001 From: Matt <63170914+matas0@users.noreply.github.com> Date: Wed, 14 Aug 2024 22:55:11 +0400 Subject: [PATCH 053/863] Added dify logo --- public/svgs/dify.png | Bin 0 -> 7324 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 public/svgs/dify.png diff --git a/public/svgs/dify.png b/public/svgs/dify.png new file mode 100644 index 0000000000000000000000000000000000000000..326acf789cfbacfbe2a749fa99cebabbf998eb7d GIT binary patch literal 7324 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 literal 0 HcmV?d00001 From c2ea8996ee2689f54f55703ba7e8c3ea144784fe Mon Sep 17 00:00:00 2001 From: Luan Estradioto Date: Tue, 25 Jun 2024 15:29:33 -0300 Subject: [PATCH 054/863] feat: fully functional terminal for command center --- .../Shared/ExecuteContainerCommand.php | 25 +-- app/Livewire/Project/Shared/Terminal.php | 46 +++++ app/Livewire/RunCommand.php | 69 +++++-- app/Models/Server.php | 29 +++ docker-compose.dev.yml | 14 +- docker-compose.prod.yml | 13 ++ docker-compose.windows.yml | 18 ++ docker-compose.yml | 6 + package-lock.json | 53 ++++- package.json | 6 +- resources/js/app.js | 15 ++ .../execute-container-command.blade.php | 13 +- .../project/shared/terminal.blade.php | 191 ++++++++++++++++++ .../views/livewire/run-command.blade.php | 20 +- terminal-server.js | 163 +++++++++++++++ 15 files changed, 624 insertions(+), 57 deletions(-) create mode 100644 app/Livewire/Project/Shared/Terminal.php create mode 100644 resources/views/livewire/project/shared/terminal.blade.php create mode 100755 terminal-server.js diff --git a/app/Livewire/Project/Shared/ExecuteContainerCommand.php b/app/Livewire/Project/Shared/ExecuteContainerCommand.php index 343915d9c..b560595b3 100644 --- a/app/Livewire/Project/Shared/ExecuteContainerCommand.php +++ b/app/Livewire/Project/Shared/ExecuteContainerCommand.php @@ -2,17 +2,15 @@ namespace App\Livewire\Project\Shared; -use App\Actions\Server\RunCommand; use App\Models\Application; use App\Models\Server; use App\Models\Service; use Illuminate\Support\Collection; +use Livewire\Attributes\On; use Livewire\Component; class ExecuteContainerCommand extends Component { - public string $command; - public string $container; public Collection $containers; @@ -23,8 +21,6 @@ class ExecuteContainerCommand extends Component public string $type; - public string $workDir = ''; - public Server $server; public Collection $servers; @@ -33,7 +29,6 @@ class ExecuteContainerCommand extends Component 'server' => 'required', 'container' => 'required', 'command' => 'required', - 'workDir' => 'nullable', ]; public function mount() @@ -115,7 +110,8 @@ class ExecuteContainerCommand extends Component } } - public function runCommand() + #[On('connectToContainer')] + public function connectToContainer() { try { if (data_get($this->parameters, 'application_uuid')) { @@ -132,14 +128,13 @@ class ExecuteContainerCommand extends Component if ($server->isForceDisabled()) { throw new \RuntimeException('Server is disabled.'); } - $cmd = "sh -c 'if [ -f ~/.profile ]; then . ~/.profile; fi; ".str_replace("'", "'\''", $this->command)."'"; - if (! empty($this->workDir)) { - $exec = "docker exec -w {$this->workDir} {$container_name} {$cmd}"; - } else { - $exec = "docker exec {$container_name} {$cmd}"; - } - $activity = RunCommand::run(server: $server, command: $exec); - $this->dispatch('activityMonitor', $activity->id); + + $this->dispatch('send-terminal-command', + true, + $container_name, + $server->uuid, + ); + } catch (\Throwable $e) { return handleError($e, $this); } diff --git a/app/Livewire/Project/Shared/Terminal.php b/app/Livewire/Project/Shared/Terminal.php new file mode 100644 index 000000000..331392118 --- /dev/null +++ b/app/Livewire/Project/Shared/Terminal.php @@ -0,0 +1,46 @@ +firstOrFail(); + + if (auth()->user()) { + $teams = auth()->user()->teams->pluck('id'); + if (! $teams->contains($server->team_id) && ! $teams->contains(0)) { + throw new \Exception('User is not part of the team that owns this server'); + } + } + + if ($isContainer) { + $status = getContainerStatus($server, $identifier); + if ($status !== 'running') { + return handleError(new \Exception('Container is not running'), $this); + } + $command = generateSshCommand($server, "docker exec -it {$identifier} sh -c 'if [ -f ~/.profile ]; then . ~/.profile; fi; if [ -n \"\$SHELL\" ]; then exec \$SHELL; else sh; fi'"); + } else { + $command = generateSshCommand($server, "sh -c 'if [ -f ~/.profile ]; then . ~/.profile; fi; if [ -n \"\$SHELL\" ]; then exec \$SHELL; else sh; fi'"); + } + + // ssh command is sent back to frontend then to websocket + // this is done because the websocket connection is not available here + // a better solution would be to remove websocket on NodeJS and work with something like + // 1. Laravel Pusher/Echo connection (not possible without a sdk) + // 2. Ratchet / Revolt / ReactPHP / Event Loop (possible but hard to implement and huge dependencies) + // 3. Just found out about this https://github.com/sirn-se/websocket-php, perhaps it can be used + $this->dispatch('send-back-command', $command); + } + + public function render() + { + return view('livewire.project.shared.terminal'); + } +} diff --git a/app/Livewire/RunCommand.php b/app/Livewire/RunCommand.php index c2d3adeea..aae02d4e1 100644 --- a/app/Livewire/RunCommand.php +++ b/app/Livewire/RunCommand.php @@ -2,42 +2,67 @@ namespace App\Livewire; -use App\Actions\Server\RunCommand as ServerRunCommand; use App\Models\Server; +use Livewire\Attributes\On; use Livewire\Component; class RunCommand extends Component { - public string $command; - - public $server; + public $selected_uuid; public $servers = []; - protected $rules = [ - 'server' => 'required', - 'command' => 'required', - ]; - - protected $validationAttributes = [ - 'server' => 'server', - 'command' => 'command', - ]; + public $containers = []; public function mount($servers) { $this->servers = $servers; - $this->server = $servers[0]->uuid; + $this->selected_uuid = $servers[0]->uuid; + $this->containers = $this->getAllActiveContainers(); } - public function runCommand() + private function getAllActiveContainers() { - $this->validate(); - try { - $activity = ServerRunCommand::run(server: Server::where('uuid', $this->server)->first(), command: $this->command); - $this->dispatch('activityMonitor', $activity->id); - } catch (\Throwable $e) { - return handleError($e, $this); - } + return Server::all()->flatMap(function ($server) { + if (! $server->isFunctional()) { + return []; + } + + return $server->definedResources() + ->filter(fn ($resource) => str_starts_with($resource->status, 'running:')) + ->map(function ($resource) use ($server) { + $container_name = $resource->uuid; + + if (class_basename($resource) === 'Application' || class_basename($resource) === 'Service') { + if ($server->isSwarm()) { + $container_name = $resource->uuid.'_'.$resource->uuid; + } else { + $current_containers = getCurrentApplicationContainerStatus($server, $resource->id, includePullrequests: true); + $container_name = data_get($current_containers->first(), 'Names'); + } + } + + return [ + 'name' => $resource->name, + 'connection_name' => $container_name, + 'uuid' => $resource->uuid, + 'status' => $resource->status, + 'server' => $server, + 'server_uuid' => $server->uuid, + ]; + }); + }); + } + + #[On('connectToContainer')] + public function connectToContainer() + { + $container = collect($this->containers)->firstWhere('uuid', $this->selected_uuid); + + $this->dispatch('send-terminal-command', + isset($container), + $container['connection_name'] ?? $this->selected_uuid, + $container['server_uuid'] ?? $this->selected_uuid + ); } } diff --git a/app/Models/Server.php b/app/Models/Server.php index 8a7325beb..337d7d7fa 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -295,6 +295,13 @@ respond 404 'service' => 'coolify-realtime', 'rule' => "Host(`{$host}`) && PathPrefix(`/app`)", ], + 'coolify-terminal-ws' => [ + 'entryPoints' => [ + 0 => 'http', + ], + 'service' => 'coolify-terminal', + 'rule' => "Host(`{$host}`) && PathPrefix(`/terminal`)", + ], ], 'services' => [ 'coolify' => [ @@ -315,6 +322,15 @@ respond 404 ], ], ], + 'coolify-terminal' => [ + 'loadBalancer' => [ + 'servers' => [ + 0 => [ + 'url' => 'http://coolify-terminal:6002', + ], + ], + ], + ], ], ], ]; @@ -344,6 +360,16 @@ respond 404 'certresolver' => 'letsencrypt', ], ]; + $traefik_dynamic_conf['http']['routers']['coolify-terminal-wss'] = [ + 'entryPoints' => [ + 0 => 'https', + ], + 'service' => 'coolify-terminal', + 'rule' => "Host(`{$host}`) && PathPrefix(`/terminal`)", + 'tls' => [ + 'certresolver' => 'letsencrypt', + ], + ]; } $yaml = Yaml::dump($traefik_dynamic_conf, 12, 2); $yaml = @@ -377,6 +403,9 @@ $schema://$host { handle /app/* { reverse_proxy coolify-realtime:6001 } + handle /terminal/* { + reverse_proxy coolify-terminal:6002 + } reverse_proxy coolify:80 }"; $base64 = base64_encode($caddy_file); diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 7eda14d41..9710e0fae 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -52,8 +52,18 @@ services: SOKETI_DEFAULT_APP_ID: "${PUSHER_APP_ID:-coolify}" SOKETI_DEFAULT_APP_KEY: "${PUSHER_APP_KEY:-coolify}" SOKETI_DEFAULT_APP_SECRET: "${PUSHER_APP_SECRET:-coolify}" + terminal: + env_file: + - .env + pull_policy: always + working_dir: /var/www/html + ports: + - "${FORWARD_TERMINAL_PORT:-6002}:6002" + volumes: + - .:/var/www/html:cached + command: sh -c "apk add --no-cache openssh-client && node --watch /var/www/html/terminal-server.js" vite: - image: node:20 + image: node:alpine pull_policy: always working_dir: /var/www/html # environment: @@ -62,7 +72,7 @@ services: - "${VITE_PORT:-5173}:${VITE_PORT:-5173}" volumes: - .:/var/www/html:cached - command: sh -c "npm install && npm run dev" + command: sh -c "apk add --no-cache make g++ python3 && npm install && npm run dev" networks: - coolify testing-host: diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index b8156cab5..5f7b5e935 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -125,6 +125,19 @@ services: interval: 5s retries: 10 timeout: 2s + terminal: + working_dir: /var/www/html + ports: + - "${TERMINAL_PORT:-6002}:6002" + volumes: + - .:/var/www/html:cached + command: sh -c "apk add --no-cache openssh-client && node /var/www/html/terminal-server.js" + healthcheck: + test: wget -qO- http://localhost:6002/ready || exit 1 + interval: 5s + retries: 10 + timeout: 2s + volumes: coolify-db: name: coolify-db diff --git a/docker-compose.windows.yml b/docker-compose.windows.yml index af5ecc0f7..ab3c7197a 100644 --- a/docker-compose.windows.yml +++ b/docker-compose.windows.yml @@ -121,6 +121,24 @@ services: interval: 5s retries: 10 timeout: 2s + terminal: + image: node:alpine + pull_policy: always + container_name: coolify-terminal + restart: always + env_file: + - .env + working_dir: /var/www/html + ports: + - "${TERMINAL_PORT:-6002}:6002" + volumes: + - .:/var/www/html:cached + command: sh -c "apk add --no-cache openssh-client && node /var/www/html/terminal-server.js" + healthcheck: + test: wget -qO- http://localhost:6002/ready || exit 1 + interval: 5s + retries: 10 + timeout: 2s volumes: coolify-db: name: coolify-db diff --git a/docker-compose.yml b/docker-compose.yml index 8eed44f8c..4f1c03127 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -28,6 +28,12 @@ services: restart: always networks: - coolify + terminal: + image: node:alpine + container_name: coolify-terminal + restart: always + networks: + - coolify networks: coolify: name: coolify diff --git a/package-lock.json b/package-lock.json index bec5a7f66..ed15acfe0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,9 +7,13 @@ "dependencies": { "@tailwindcss/forms": "0.5.7", "@tailwindcss/typography": "0.5.13", + "@xterm/addon-fit": "^0.10.0", + "@xterm/xterm": "^5.5.0", "alpinejs": "3.14.0", "ioredis": "5.4.1", - "tailwindcss-scrollbar": "0.1.0" + "node-pty": "^1.0.0", + "tailwindcss-scrollbar": "0.1.0", + "ws": "^8.17.0" }, "devDependencies": { "@vitejs/plugin-vue": "4.5.1", @@ -692,6 +696,19 @@ "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.1.5.tgz", "integrity": "sha512-oJ4F3TnvpXaQwZJNF3ZK+kLPHKarDmJjJ6jyzVNDKH9md1dptjC7lWR//jrGuLdek/U6iltWxqAnYOu8gCiOvA==" }, + "node_modules/@xterm/addon-fit": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@xterm/addon-fit/-/addon-fit-0.10.0.tgz", + "integrity": "sha512-UFYkDm4HUahf2lnEyHvio51TNGiLK66mqP2JoATy7hRZeXaGMRDr00JiSF7m63vR5WKATF605yEggJKsw0JpMQ==", + "peerDependencies": { + "@xterm/xterm": "^5.0.0" + } + }, + "node_modules/@xterm/xterm": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@xterm/xterm/-/xterm-5.5.0.tgz", + "integrity": "sha512-hqJHYaQb5OptNunnyAnkHyM8aCjZ1MEIDTQu1iIbbTD/xops91NB5yq1ZK/dC2JDbVWtF23zUtl9JE2NqwT87A==" + }, "node_modules/alpinejs": { "version": "3.14.0", "resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-3.14.0.tgz", @@ -1474,6 +1491,11 @@ "thenify-all": "^1.0.0" } }, + "node_modules/nan": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.20.0.tgz", + "integrity": "sha512-bk3gXBZDGILuuo/6sKtr0DQmSThYHLtNCdSdXk9YkxD/jK6X2vmCyyXBBxyqZ4XcnzTyYEAThfX3DCEnLf6igw==" + }, "node_modules/nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", @@ -1491,6 +1513,15 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/node-pty": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-pty/-/node-pty-1.0.0.tgz", + "integrity": "sha512-wtBMWWS7dFZm/VgqElrTvtfMq4GzJ6+edFI0Y0zyzygUSZMgZdraDUMUhCIvkjhJjme15qWmbyJbtAx4ot4uZA==", + "hasInstallScript": true, + "dependencies": { + "nan": "^2.17.0" + } + }, "node_modules/node-releases": { "version": "2.0.14", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", @@ -2123,6 +2154,26 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, + "node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/yaml": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz", diff --git a/package.json b/package.json index b4609a025..9c2541ecc 100644 --- a/package.json +++ b/package.json @@ -20,8 +20,12 @@ "dependencies": { "@tailwindcss/forms": "0.5.7", "@tailwindcss/typography": "0.5.13", + "@xterm/addon-fit": "^0.10.0", + "@xterm/xterm": "^5.5.0", "alpinejs": "3.14.0", "ioredis": "5.4.1", - "tailwindcss-scrollbar": "0.1.0" + "node-pty": "^1.0.0", + "tailwindcss-scrollbar": "0.1.0", + "ws": "^8.17.0" } } diff --git a/resources/js/app.js b/resources/js/app.js index befec919e..f450cbe29 100644 --- a/resources/js/app.js +++ b/resources/js/app.js @@ -4,3 +4,18 @@ // const app = createApp({}); // app.component("magic-bar", MagicBar); // app.mount("#vue"); + +import { Terminal } from '@xterm/xterm'; +import '@xterm/xterm/css/xterm.css'; +import { FitAddon } from '@xterm/addon-fit'; + +if (!window.term) { + window.term = new Terminal({ + cols: 80, + rows: 30, + fontFamily: '"Fira Code", courier-new, courier, monospace, "Powerline Extra Symbols"', + cursorBlink: true + }); + window.fitAddon = new FitAddon(); + window.term.loadAddon(window.fitAddon); +} diff --git a/resources/views/livewire/project/shared/execute-container-command.blade.php b/resources/views/livewire/project/shared/execute-container-command.blade.php index 680d6e0e1..167f4178b 100644 --- a/resources/views/livewire/project/shared/execute-container-command.blade.php +++ b/resources/views/livewire/project/shared/execute-container-command.blade.php @@ -22,11 +22,8 @@
@if (count($containers) > 0) -
-
- - -
+ @if (data_get($this->parameters, 'application_uuid')) @@ -47,14 +44,14 @@ @endif - Run + Start Connection
@else
No containers are not running.
@endif
-
- +
+
diff --git a/resources/views/livewire/project/shared/terminal.blade.php b/resources/views/livewire/project/shared/terminal.blade.php new file mode 100644 index 000000000..ecb1a0e50 --- /dev/null +++ b/resources/views/livewire/project/shared/terminal.blade.php @@ -0,0 +1,191 @@ +
+
+
+ (connection closed) +
+
+
+
+ + +
+ + @script + + @endscript +
diff --git a/resources/views/livewire/run-command.blade.php b/resources/views/livewire/run-command.blade.php index 7911f0470..1f0162940 100644 --- a/resources/views/livewire/run-command.blade.php +++ b/resources/views/livewire/run-command.blade.php @@ -1,19 +1,23 @@
-
- - + + @foreach ($servers as $server) @if ($loop->first) @else @endif + @foreach ($containers as $container) + @if ($container['server_uuid'] == $server->uuid) + + @endif + @endforeach @endforeach - Execute Command - + Start Connection -
- -
+
diff --git a/terminal-server.js b/terminal-server.js new file mode 100755 index 000000000..3923c3b5c --- /dev/null +++ b/terminal-server.js @@ -0,0 +1,163 @@ +import { WebSocketServer } from 'ws'; +import http from 'http'; +import pty from 'node-pty'; + +const server = http.createServer((req, res) => { + if (req.url === '/ready') { + res.writeHead(200, { 'Content-Type': 'text/plain' }); + res.end('OK'); + } else { + res.writeHead(404, { 'Content-Type': 'text/plain' }); + res.end('Not Found'); + } +}); + +const wss = new WebSocketServer({ server, path: '/terminal' }); +const userSessions = new Map(); + +wss.on('connection', (ws) => { + const userId = generateUserId(); + const userSession = { ws, userId, ptyProcess: null, isActive: false }; + userSessions.set(userId, userSession); + + ws.on('message', (message) => handleMessage(userSession, message)); + ws.on('error', (err) => handleError(err, userId)); + ws.on('close', () => handleClose(userId)); +}); + +const messageHandlers = { + message: (session, data) => session.ptyProcess.write(data), + resize: (session, { cols, rows }) => session.ptyProcess.resize(cols, rows), + pause: (session) => session.ptyProcess.pause(), + resume: (session) => session.ptyProcess.resume(), + checkActive: (session, data) => { + if (data === 'force' && session.isActive) { + killPtyProcess(session.userId); + } else { + session.ws.send(session.isActive); + } + }, + command: (session, data) => handleCommand(session.ws, data, session.userId) +}; + +function handleMessage(userSession, message) { + const parsed = parseMessage(message); + if (!parsed) return; + + Object.entries(parsed).forEach(([key, value]) => { + const handler = messageHandlers[key]; + if (handler && (userSession.isActive || key === 'checkActive' || key === 'command')) { + handler(userSession, value); + } + }); +} + +function parseMessage(message) { + try { + return JSON.parse(message); + } catch (e) { + console.error('Failed to parse message:', e); + return null; + } +} + +async function handleCommand(ws, command, userId) { + const userSession = userSessions.get(userId); + + if (userSession && userSession.isActive) { + await killPtyProcess(userId); + } + + const commandString = command[0].split('\n').join(' '); + const timeout = extractTimeout(commandString); + const sshArgs = extractSshArgs(commandString); + const hereDocContent = extractHereDocContent(commandString); + const options = { + name: 'xterm-color', + cols: 80, + rows: 30, + cwd: process.env.HOME, + env: process.env + }; + + // NOTE: - Initiates a process within the Terminal container + // Establishes an SSH connection to root@coolify with RequestTTY enabled + // Executes the 'docker exec' command to connect to a specific container + // If the user types 'exit', it terminates the container connection and reverts to the server. + const ptyProcess = pty.spawn('ssh', sshArgs.concat(['bash']), options); + userSession.ptyProcess = ptyProcess; + userSession.isActive = true; + ptyProcess.write(hereDocContent + '\n'); + ptyProcess.write('clear\n'); + + ws.send('pty-ready'); + + ptyProcess.onData((data) => ws.send(data)); + + ptyProcess.onExit(({ exitCode, signal }) => { + console.error(`Process exited with code ${exitCode} and signal ${signal}`); + userSession.isActive = false; + }); + + if (timeout) { + setTimeout(async () => { + await killPtyProcess(userId); + }, timeout * 1000); + } +} + +async function handleError(err, userId) { + console.error('WebSocket error:', err); + await killPtyProcess(userId); +} + +async function handleClose(userId) { + await killPtyProcess(userId); + userSessions.delete(userId); +} + +async function killPtyProcess(userId) { + const session = userSessions.get(userId); + if (!session?.ptyProcess) return false; + + return new Promise((resolve) => { + session.ptyProcess.on('exit', () => { + session.isActive = false; + resolve(true); + }); + + session.ptyProcess.kill(); + }); +} + +function generateUserId() { + return Math.random().toString(36).substring(2, 11); +} + +function extractTimeout(commandString) { + const timeoutMatch = commandString.match(/timeout (\d+)/); + return timeoutMatch ? parseInt(timeoutMatch[1], 10) : null; +} + +function extractSshArgs(commandString) { + const sshCommandMatch = commandString.match(/ssh (.+?) 'bash -se'/); + let sshArgs = sshCommandMatch ? sshCommandMatch[1].split(' ') : []; + sshArgs = sshArgs.map(arg => arg === 'RequestTTY=no' ? 'RequestTTY=yes' : arg); + if (!sshArgs.includes('RequestTTY=yes')) { + sshArgs.push('-o', 'RequestTTY=yes'); + } + return sshArgs; +} + +function extractHereDocContent(commandString) { + const delimiterMatch = commandString.match(/<< (\S+)/); + const delimiter = delimiterMatch ? delimiterMatch[1] : null; + const escapedDelimiter = delimiter.slice(1).trim().replace(/[/\-\\^$*+?.()|[\]{}]/g, '\\$&'); + const hereDocRegex = new RegExp(`<< \\\\${escapedDelimiter}([\\s\\S\\.]*?)${escapedDelimiter}`); + const hereDocMatch = commandString.match(hereDocRegex); + return hereDocMatch ? hereDocMatch[1] : ''; +} + +server.listen(6002, () => { + console.log('Server listening on port 6002'); +}); From 548fc21e4008b2723d81f273535b3b0c82a6acc6 Mon Sep 17 00:00:00 2001 From: Luan Estradioto Date: Thu, 15 Aug 2024 02:38:06 -0300 Subject: [PATCH 055/863] added ws authentication --- app/Livewire/RunCommand.php | 5 +- package-lock.json | 32 +- package.json | 4 +- .../project/shared/terminal.blade.php | 309 +++++++++--------- routes/web.php | 6 + terminal-server.js | 43 ++- 6 files changed, 238 insertions(+), 161 deletions(-) diff --git a/app/Livewire/RunCommand.php b/app/Livewire/RunCommand.php index aae02d4e1..2d01cbca0 100644 --- a/app/Livewire/RunCommand.php +++ b/app/Livewire/RunCommand.php @@ -29,7 +29,10 @@ class RunCommand extends Component } return $server->definedResources() - ->filter(fn ($resource) => str_starts_with($resource->status, 'running:')) + ->filter(function ($resource) { + $status = method_exists($resource, 'realStatus') ? $resource->realStatus() : (method_exists($resource, 'status') ? $resource->status() : 'exited'); + return str_starts_with($status, 'running:'); + }) ->map(function ($resource) use ($server) { $container_name = $resource->uuid; diff --git a/package-lock.json b/package-lock.json index ed15acfe0..a9e742135 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,8 @@ "@xterm/addon-fit": "^0.10.0", "@xterm/xterm": "^5.5.0", "alpinejs": "3.14.0", + "cookie": "^0.6.0", + "dotenv": "^16.4.5", "ioredis": "5.4.1", "node-pty": "^1.0.0", "tailwindcss-scrollbar": "0.1.0", @@ -18,7 +20,7 @@ "devDependencies": { "@vitejs/plugin-vue": "4.5.1", "autoprefixer": "10.4.19", - "axios": "1.7.2", + "axios": "^1.7.4", "laravel-echo": "1.16.1", "laravel-vite-plugin": "0.8.1", "postcss": "8.4.38", @@ -783,10 +785,11 @@ } }, "node_modules/axios": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz", - "integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==", + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz", + "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==", "dev": true, + "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", @@ -956,6 +959,15 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, + "node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -1016,6 +1028,18 @@ "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/electron-to-chromium": { "version": "1.4.692", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.692.tgz", diff --git a/package.json b/package.json index 9c2541ecc..882ad2e01 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "devDependencies": { "@vitejs/plugin-vue": "4.5.1", "autoprefixer": "10.4.19", - "axios": "1.7.2", + "axios": "^1.7.4", "laravel-echo": "1.16.1", "laravel-vite-plugin": "0.8.1", "postcss": "8.4.38", @@ -23,6 +23,8 @@ "@xterm/addon-fit": "^0.10.0", "@xterm/xterm": "^5.5.0", "alpinejs": "3.14.0", + "cookie": "^0.6.0", + "dotenv": "^16.4.5", "ioredis": "5.4.1", "node-pty": "^1.0.0", "tailwindcss-scrollbar": "0.1.0", diff --git a/resources/views/livewire/project/shared/terminal.blade.php b/resources/views/livewire/project/shared/terminal.blade.php index ecb1a0e50..4e1a086e2 100644 --- a/resources/views/livewire/project/shared/terminal.blade.php +++ b/resources/views/livewire/project/shared/terminal.blade.php @@ -24,168 +24,169 @@ @script - + // Type CTRL + D or exit in the terminal + if (data === '\x04' || (data === '\r' && stripAnsiCommands(commandBuffer).trim() === 'exit')) { + checkIfProcessIsRunningAndKillIt(); + setTimeout(() => { + term.reset(); + term.write('(connection closed)'); + $data.terminalActive = false; + }, 500); + commandBuffer = ''; + } else if (data === '\r') { + commandBuffer = ''; + } else { + commandBuffer += data; + } + }); + + function stripAnsiCommands(input) { + return input.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, ''); + } + + // Copy and paste + // Enables ctrl + c and ctrl + v + // defaults otherwise to ctrl + insert, shift + insert + term.attachCustomKeyEventHandler((arg) => { + if (arg.ctrlKey && arg.code === "KeyV" && arg.type === "keydown") { + navigator.clipboard.readText() + .then(text => { + socket.send(JSON.stringify({ + message: text + })); + }) + }; + + if (arg.ctrlKey && arg.code === "KeyC" && arg.type === "keydown") { + const selection = term.getSelection(); + if (selection) { + navigator.clipboard.writeText(selection); + return false; + } + } + return true; + }); + + $wire.on('send-back-command', function(command) { + socket.send(JSON.stringify({ + command: command + })); + }); + + window.addEventListener('beforeunload', function(e) { + checkIfProcessIsRunningAndKillIt(); + }); + + function checkIfProcessIsRunningAndKillIt() { + socket.send(JSON.stringify({ + checkActive: 'force' + })); + } + + window.onresize = function() { + $data.resizeTerminal() + }; + + Alpine.data('data', () => ({ + fullscreen: false, + terminalActive: false, + init() { + this.$watch('terminalActive', (value) => { + this.$nextTick(() => { + if (value) { + $refs.terminalWrapper.style.display = 'block'; + this.resizeTerminal(); + } else { + $refs.terminalWrapper.style.display = 'none'; + } + }); + }); + }, + makeFullscreen() { + this.fullscreen = !this.fullscreen; + $nextTick(() => { + this.resizeTerminal() + }) + }, + + resizeTerminal() { + if (!this.terminalActive) return; + + fitAddon.fit(); + const height = $refs.terminalWrapper.clientHeight; + const rows = height / term._core._renderService._charSizeService.height - 1; + var termWidth = term.cols; + var termHeight = parseInt(rows.toString(), 10); + term.resize(termWidth, termHeight); + socket.send(JSON.stringify({ + resize: { + cols: termWidth, + rows: termHeight + } + })); + } + })); + + initializeWebSocket(); + @endscript - + \ No newline at end of file diff --git a/routes/web.php b/routes/web.php index e2ccfc704..01cf2762b 100644 --- a/routes/web.php +++ b/routes/web.php @@ -154,6 +154,12 @@ Route::middleware(['auth', 'verified'])->group(function () { }); Route::get('/command-center', CommandCenterIndex::class)->name('command-center'); + Route::post('/terminal/auth', function () { + if (auth()->check()) { + return response()->json(['authenticated' => true], 200); + } + return response()->json(['authenticated' => false], 401); + })->name('terminal.auth'); Route::prefix('invitations')->group(function () { Route::get('/{uuid}', [Controller::class, 'accept_invitation'])->name('team.invitation.accept'); diff --git a/terminal-server.js b/terminal-server.js index 3923c3b5c..a1555bf30 100755 --- a/terminal-server.js +++ b/terminal-server.js @@ -1,6 +1,9 @@ import { WebSocketServer } from 'ws'; import http from 'http'; import pty from 'node-pty'; +import axios from 'axios'; +import cookie from 'cookie'; +import 'dotenv/config' const server = http.createServer((req, res) => { if (req.url === '/ready') { @@ -12,7 +15,45 @@ const server = http.createServer((req, res) => { } }); -const wss = new WebSocketServer({ server, path: '/terminal' }); +const verifyClient = async (info, callback) => { + const cookies = cookie.parse(info.req.headers.cookie || ''); + const origin = new URL(info.origin); + const protocol = origin.protocol; + const xsrfToken = cookies['XSRF-TOKEN']; + + // Generate session cookie name based on APP_NAME + const appName = process.env.APP_NAME || 'laravel'; + const sessionCookieName = `${appName.replace(/[^a-zA-Z0-9]/g, '_').toLowerCase()}_session`; + const laravelSession = cookies[sessionCookieName]; + + // Verify presence of required tokens + if (!laravelSession || !xsrfToken) { + return callback(false, 401, 'Unauthorized: Missing required tokens'); + } + + try { + // Authenticate with Laravel backend + const response = await axios.post(`${protocol}//coolify/terminal/auth`, null, { + headers: { + 'Cookie': `${sessionCookieName}=${laravelSession}`, + 'X-XSRF-TOKEN': xsrfToken + }, + }); + + if (response.status === 200) { + // Authentication successful + callback(true); + } else { + callback(false, 401, 'Unauthorized: Invalid credentials'); + } + } catch (error) { + console.error('Authentication error:', error.message); + callback(false, 500, 'Internal Server Error'); + } +}; + + +const wss = new WebSocketServer({ server, path: '/terminal', verifyClient: verifyClient }); const userSessions = new Map(); wss.on('connection', (ws) => { From 2b8c9920d85c82756c2e4a1ac9d0ac1443e0295d Mon Sep 17 00:00:00 2001 From: Luan Estradioto Date: Thu, 15 Aug 2024 20:52:50 -0300 Subject: [PATCH 056/863] removed extra container and added new process to soketi container --- app/Models/Server.php | 4 +- docker-compose.dev.yml | 20 +++++----- docker-compose.prod.yml | 22 +++++------ docker-compose.windows.yml | 31 ++++++--------- docker-compose.yml | 6 --- docker/soketi-entrypoint/soketi-entrypoint.sh | 39 +++++++++++++++++++ 6 files changed, 70 insertions(+), 52 deletions(-) create mode 100644 docker/soketi-entrypoint/soketi-entrypoint.sh diff --git a/app/Models/Server.php b/app/Models/Server.php index 337d7d7fa..44746324b 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -326,7 +326,7 @@ respond 404 'loadBalancer' => [ 'servers' => [ 0 => [ - 'url' => 'http://coolify-terminal:6002', + 'url' => 'http://coolify-realtime:6002', ], ], ], @@ -404,7 +404,7 @@ $schema://$host { reverse_proxy coolify-realtime:6001 } handle /terminal/* { - reverse_proxy coolify-terminal:6002 + reverse_proxy coolify-realtime:6002 } reverse_proxy coolify:80 }"; diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 9710e0fae..64eb1d2a4 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -47,21 +47,19 @@ services: - .env ports: - "${FORWARD_SOKETI_PORT:-6001}:6001" + - "6002:6002" + volumes: + - ./docker/soketi-entrypoint/soketi-entrypoint.sh:/soketi-entrypoint.sh + - ./package.json:/terminal/package.json + - ./package-lock.json:/terminal/package-lock.json + - ./terminal-server.js:/terminal/terminal-server.js + - ./storage:/var/www/html/storage + entrypoint: ["/bin/sh", "/soketi-entrypoint.sh"] environment: SOKETI_DEBUG: "false" SOKETI_DEFAULT_APP_ID: "${PUSHER_APP_ID:-coolify}" SOKETI_DEFAULT_APP_KEY: "${PUSHER_APP_KEY:-coolify}" SOKETI_DEFAULT_APP_SECRET: "${PUSHER_APP_SECRET:-coolify}" - terminal: - env_file: - - .env - pull_policy: always - working_dir: /var/www/html - ports: - - "${FORWARD_TERMINAL_PORT:-6002}:6002" - volumes: - - .:/var/www/html:cached - command: sh -c "apk add --no-cache openssh-client && node --watch /var/www/html/terminal-server.js" vite: image: node:alpine pull_policy: always @@ -72,7 +70,7 @@ services: - "${VITE_PORT:-5173}:${VITE_PORT:-5173}" volumes: - .:/var/www/html:cached - command: sh -c "apk add --no-cache make g++ python3 && npm install && npm run dev" + command: sh -c "npm install && npm run dev" networks: - coolify testing-host: diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index 5f7b5e935..5fc6a9919 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -115,25 +115,21 @@ services: soketi: ports: - "${SOKETI_PORT:-6001}:6001" + - "6002:6002" + volumes: + - ./docker/soketi-entrypoint/soketi-entrypoint.sh:/soketi-entrypoint.sh + - ./package.json:/terminal/package.json + - ./package-lock.json:/terminal/package-lock.json + - ./terminal-server.js:/terminal/terminal-server.js + - ./storage:/var/www/html/storage + entrypoint: ["/bin/sh", "/soketi-entrypoint.sh"] environment: SOKETI_DEBUG: "${SOKETI_DEBUG:-false}" SOKETI_DEFAULT_APP_ID: "${PUSHER_APP_ID}" SOKETI_DEFAULT_APP_KEY: "${PUSHER_APP_KEY}" SOKETI_DEFAULT_APP_SECRET: "${PUSHER_APP_SECRET}" healthcheck: - test: wget -qO- http://127.0.0.1:6001/ready || exit 1 - interval: 5s - retries: 10 - timeout: 2s - terminal: - working_dir: /var/www/html - ports: - - "${TERMINAL_PORT:-6002}:6002" - volumes: - - .:/var/www/html:cached - command: sh -c "apk add --no-cache openssh-client && node /var/www/html/terminal-server.js" - healthcheck: - test: wget -qO- http://localhost:6002/ready || exit 1 + test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:6001/ready && wget -qO- http://127.0.0.1:6002/ready || exit 1"] interval: 5s retries: 10 timeout: 2s diff --git a/docker-compose.windows.yml b/docker-compose.windows.yml index ab3c7197a..1b800a5d6 100644 --- a/docker-compose.windows.yml +++ b/docker-compose.windows.yml @@ -102,7 +102,7 @@ services: interval: 5s retries: 10 timeout: 2s - soketi: +soketi: image: 'quay.io/soketi/soketi:1.6-16-alpine' pull_policy: always container_name: coolify-realtime @@ -111,34 +111,25 @@ services: - .env ports: - "${SOKETI_PORT:-6001}:6001" + - "6002:6002" + volumes: + - ./docker/soketi-entrypoint/soketi-entrypoint.sh:/soketi-entrypoint.sh + - ./package.json:/terminal/package.json + - ./package-lock.json:/terminal/package-lock.json + - ./terminal-server.js:/terminal/terminal-server.js + - ./storage:/var/www/html/storage + entrypoint: ["/bin/sh", "/soketi-entrypoint.sh"] environment: SOKETI_DEBUG: "${SOKETI_DEBUG:-false}" SOKETI_DEFAULT_APP_ID: "${PUSHER_APP_ID}" SOKETI_DEFAULT_APP_KEY: "${PUSHER_APP_KEY}" SOKETI_DEFAULT_APP_SECRET: "${PUSHER_APP_SECRET}" healthcheck: - test: wget -qO- http://localhost:6001/ready || exit 1 - interval: 5s - retries: 10 - timeout: 2s - terminal: - image: node:alpine - pull_policy: always - container_name: coolify-terminal - restart: always - env_file: - - .env - working_dir: /var/www/html - ports: - - "${TERMINAL_PORT:-6002}:6002" - volumes: - - .:/var/www/html:cached - command: sh -c "apk add --no-cache openssh-client && node /var/www/html/terminal-server.js" - healthcheck: - test: wget -qO- http://localhost:6002/ready || exit 1 + test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:6001/ready && wget -qO- http://127.0.0.1:6002/ready || exit 1"] interval: 5s retries: 10 timeout: 2s + volumes: coolify-db: name: coolify-db diff --git a/docker-compose.yml b/docker-compose.yml index 4f1c03127..8eed44f8c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -28,12 +28,6 @@ services: restart: always networks: - coolify - terminal: - image: node:alpine - container_name: coolify-terminal - restart: always - networks: - - coolify networks: coolify: name: coolify diff --git a/docker/soketi-entrypoint/soketi-entrypoint.sh b/docker/soketi-entrypoint/soketi-entrypoint.sh new file mode 100644 index 000000000..808e306e7 --- /dev/null +++ b/docker/soketi-entrypoint/soketi-entrypoint.sh @@ -0,0 +1,39 @@ +#!/bin/sh + +# Install openssh-client +apk add --no-cache openssh-client make g++ python3 + +cd /terminal + +# Install npm dependencies +npm ci + +# Rebuild node-pty +npm rebuild node-pty --update-binary + +# Function to timestamp logs +timestamp() { + date "+%Y-%m-%d %H:%M:%S" +} + +# Start the terminal server in the background with logging +node --watch /terminal/terminal-server.js > >(while read line; do echo "$(timestamp) [TERMINAL] $line"; done) 2>&1 & +TERMINAL_PID=$! + +# Start the Soketi process in the background with logging +node /app/bin/server.js start > >(while read line; do echo "$(timestamp) [SOKETI] $line"; done) 2>&1 & +SOKETI_PID=$! + +# Function to forward signals to child processes +forward_signal() { + kill -$1 $TERMINAL_PID $SOKETI_PID +} + +# Forward SIGTERM to child processes +trap 'forward_signal TERM' TERM + +# Wait for any process to exit +wait -n + +# Exit with status of process that exited first +exit $? \ No newline at end of file From 4f23d3880d49fc9797f19f3886a459ab1540d5b9 Mon Sep 17 00:00:00 2001 From: sroepges <47949518+sroepges@users.noreply.github.com> Date: Fri, 16 Aug 2024 13:42:42 +0200 Subject: [PATCH 057/863] fix: update mattermost image tag and add default port --- templates/compose/mattermost.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/templates/compose/mattermost.yaml b/templates/compose/mattermost.yaml index ce3e09531..b750aa6fd 100644 --- a/templates/compose/mattermost.yaml +++ b/templates/compose/mattermost.yaml @@ -2,10 +2,11 @@ # documentation: https://docs.mattermost.com # slogan: Mattermost is an open source, self-hosted Slack-alternative. # tags: mattermost,slack,alternative +# port: 8065 services: mattermost: - image: mattermost/mattermost-team-edition:9 + image: mattermost/mattermost-team-edition:release-9 volumes: - mattermost-data:/mattermost environment: From 7f59efd27cda84a4d88d8d810520c25204868dbc Mon Sep 17 00:00:00 2001 From: sroepges <47949518+sroepges@users.noreply.github.com> Date: Fri, 16 Aug 2024 15:23:54 +0200 Subject: [PATCH 058/863] chore: add mattermost logo as svg --- public/svgs/mattermost.svg | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 public/svgs/mattermost.svg diff --git a/public/svgs/mattermost.svg b/public/svgs/mattermost.svg new file mode 100644 index 000000000..b01d38eb7 --- /dev/null +++ b/public/svgs/mattermost.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file From b8cdb40ce52ee3b7e2e21dbc1b23f70babcfc80f Mon Sep 17 00:00:00 2001 From: sroepges <47949518+sroepges@users.noreply.github.com> Date: Fri, 16 Aug 2024 15:26:42 +0200 Subject: [PATCH 059/863] chore: add mattermost svg to compose --- templates/compose/mattermost.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/templates/compose/mattermost.yaml b/templates/compose/mattermost.yaml index b750aa6fd..2eda3e4f5 100644 --- a/templates/compose/mattermost.yaml +++ b/templates/compose/mattermost.yaml @@ -2,6 +2,7 @@ # documentation: https://docs.mattermost.com # slogan: Mattermost is an open source, self-hosted Slack-alternative. # tags: mattermost,slack,alternative +# logo: svgs/mattermost.svg # port: 8065 services: From ce926afdaad018d2b575e86dc5d4e7fd06ed768f Mon Sep 17 00:00:00 2001 From: Alex Renoki Date: Sat, 17 Aug 2024 06:16:38 +0300 Subject: [PATCH 060/863] Bump to v2 --- templates/compose/langfuse.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/compose/langfuse.yaml b/templates/compose/langfuse.yaml index 1512b0f07..400e6ec75 100644 --- a/templates/compose/langfuse.yaml +++ b/templates/compose/langfuse.yaml @@ -8,7 +8,7 @@ version: "3" services: langfuse: - image: langfuse/langfuse + image: langfuse/langfuse:2 restart: always environment: - DATABASE_URL=postgresql://${SERVICE_USER_POSTGRES}:${SERVICE_PASSWORD_POSTGRES}@postgres:5432/${POSTGRES_DB:-langfuse} From 71bb1f5e17c6b4947adb5c0c9f9403fbaa1cc030 Mon Sep 17 00:00:00 2001 From: Alex Renoki Date: Sat, 17 Aug 2024 06:20:42 +0300 Subject: [PATCH 061/863] Added litellm --- public/svgs/litellm.svg | 1 + templates/compose/litellm.yaml | 177 +++++++++++++++++++++++++++++++++ 2 files changed, 178 insertions(+) create mode 100644 public/svgs/litellm.svg create mode 100644 templates/compose/litellm.yaml diff --git a/public/svgs/litellm.svg b/public/svgs/litellm.svg new file mode 100644 index 000000000..01830c3f6 --- /dev/null +++ b/public/svgs/litellm.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/compose/litellm.yaml b/templates/compose/litellm.yaml new file mode 100644 index 000000000..b16e08fbe --- /dev/null +++ b/templates/compose/litellm.yaml @@ -0,0 +1,177 @@ +# documentation: https://docs.litellm.ai +# slogan: Call all LLM APIs using the OpenAI format. Use Bedrock, Azure, OpenAI, Cohere, Anthropic, Ollama, Sagemaker, HuggingFace, Replicate, Groq (100+ LLMs) +# tags: ai, qdrant, weaviate, langchain, openai, gpt, llm, lmops, anthropic, cohere, ollama, sagemaker, huggingface, replicate, groq +# logo: svgs/litellm.svg +# port: 4000 + +volumes: + pg-data: null + redis-data: null + +services: + litellm: + image: "ghcr.io/berriai/litellm-database:main-latest" + restart: always + depends_on: + postgres: + condition: service_healthy + redis: + condition: service_healthy + environment: + - LITELLM_LOG=ERROR + - LITELLM_MODE=PRODUCTION + - "LITELLM_MASTER_KEY=${SERVICE_PASSWORD_32_LITELLM_MASTER_KEY}" + - "UI_USERNAME=${SERVICE_USER_UI}" + - "UI_PASSWORD=${SERVICE_PASSWORD_UI}" + - "DATABASE_URL=postgresql://${SERVICE_USER_POSTGRES}:${SERVICE_PASSWORD_POSTGRES}@postgres:5432/${POSTGRES_DB:-litellm}" + - REDIS_HOST=redis + - REDIS_PORT=6379 + - "POSTGRES_USER=${SERVICE_USER_POSTGRES}" + - "POSTGRES_PASSWORD=${SERVICE_PASSWORD_POSTGRES}" + - "POSTGRES_DB=${POSTGRES_DB:-litellm}" + - "OPENAI_API_KEY=${OPENAI_API_KEY}" + - "OPENAI_API_BASE=${OPENAI_API_BASE}" + - "ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}" + - "ANTHROPIC_API_BASE=${ANTHROPIC_API_BASE}" + - "VOYAGE_API_KEY=${VOYAGE_API_KEY}" + - "VOYAGE_API_BASE=${VOYAGE_API_BASE}" + volumes: + - "./litellm-config.yaml:/app/config.yaml" + - type: bind + source: ./docker/app/config.yaml + target: /app/config.yaml + content: | + general_settings: + proxy_batch_write_at: 60 + + router_settings: + routing_strategy: usage-based-routing-v2 + redis_host: os.environ/REDIS_HOST + redis_port: os.environ/REDIS_PORT + redis_password: os.environ/REDIS_PASSWORD + enable_pre_call_check: true + + litellm_settings: + set_verbose: false + json_logs: true + log_raw_request_response: true + # turn_off_message_logging: false + # redact_user_api_key_info: false + drop_params: true + # max_budget: 100 + # budget_duration: 30d + num_retries: 3 + request_timeout: 600 + telemetry: false + cache: true + cache_params: + type: redis + host: os.environ/REDIS_HOST + port: os.environ/REDIS_PORT + password: os.environ/REDIS_PASSWORD + namespace: "litellm_cache" + ttl: 600 + # success_callback: + # - "langfuse" + # - "prometheus" + # failure_callback: + # - "langfuse" + # - "prometheus" + model_list: + # OpenAI + - model_name: gpt-3.5-turbo + litellm_params: + model: openai/gpt-3.5-turbo + api_key: os.environ/OPENAI_API_KEY + api_base: os.environ/OPENAI_API_BASE + - model_name: gpt-4 + litellm_params: + model: openai/gpt-4 + api_key: os.environ/OPENAI_API_KEY + api_base: os.environ/OPENAI_API_BASE + - model_name: gpt-4o + litellm_params: + model: openai/gpt-4o + api_key: os.environ/OPENAI_API_KEY + api_base: os.environ/OPENAI_API_BASE + - model_name: gpt-4o-mini + litellm_params: + model: openai/gpt-4o-mini + api_key: os.environ/OPENAI_API_KEY + api_base: os.environ/OPENAI_API_BASE + # Anthropic + - model_name: claude-3-haiku + litellm_params: + model: claude-3-haiku-20240307 + api_key: "os.environ/ANTHROPIC_API_KEY" + api_base: "os.environ/ANTHROPIC_API_BASE" + - model_name: claude-3.5-sonnet + litellm_params: + model: claude-3-5-sonnet-20240620 + api_key: "os.environ/ANTHROPIC_API_KEY" + api_base: "os.environ/ANTHROPIC_API_BASE" + # VoyageAI + - model_name: voyage-law-2 + model_info: + output_vector_size: 1024 + litellm_params: + model: voyage/voyage-law-2 + api_key: "os.environ/VOYAGE_API_KEY" + api_base: "os.environ/VOYAGE_API_BASE" + rpm: 300 + tpm: 1000000 + - model_name: voyage-multilingual-2 + model_info: + mode: embedding + max_tokens: 32000 + max_input_tokens: 32000 + output_vector_size: 1024 + litellm_params: + model: voyage/voyage-multilingual-2 + api_key: "os.environ/VOYAGE_API_KEY" + api_base: "os.environ/VOYAGE_API_BASE" + input_cost_per_token: 0.00000012 + output_cost_per_token: 0 + rpm: 300 + tpm: 1000000 + healthcheck: + test: + - CMD + - python + - "-c" + - "import requests as r;r.get('http://127.0.0.1:4000/health/liveliness').raise_for_status()" + interval: 5s + timeout: 5s + retries: 3 + command: + - "--config" + - /app/config.yaml + - "--port" + - "4000" + - "--num_workers" + - "8" + postgres: + image: "postgres:16-alpine" + environment: + - POSTGRES_DB=${POSTGRES_DB:-litellm} + - POSTGRES_PASSWORD=$SERVICE_PASSWORD_POSTGRES + - POSTGRES_USER=$SERVICE_USER_POSTGRES + volumes: + - "pg-data:/var/lib/postgresql/data" + healthcheck: + test: + - CMD-SHELL + - "pg_isready -h localhost -U ${POSTGRES_USER} -d ${POSTGRES_DB}" + interval: 5s + timeout: 5s + retries: 3 + redis: + image: redis:7-alpine + command: redis-server --appendonly yes + volumes: + - redis-data:/data + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 5s + timeout: 5s + retries: 3 From a6f457f2f3874179927180b37f3ef5fa803d1af7 Mon Sep 17 00:00:00 2001 From: christiankolbow Date: Sat, 17 Aug 2024 16:36:52 +0200 Subject: [PATCH 062/863] feat: add keycloak template --- public/svgs/keycloak.svg | 55 ++++++++++++++++++ templates/compose/keycloak-with-postgres.yaml | 58 +++++++++++++++++++ templates/compose/keycloak.yaml | 35 +++++++++++ 3 files changed, 148 insertions(+) create mode 100644 public/svgs/keycloak.svg create mode 100644 templates/compose/keycloak-with-postgres.yaml create mode 100644 templates/compose/keycloak.yaml diff --git a/public/svgs/keycloak.svg b/public/svgs/keycloak.svg new file mode 100644 index 000000000..849ac2759 --- /dev/null +++ b/public/svgs/keycloak.svg @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/templates/compose/keycloak-with-postgres.yaml b/templates/compose/keycloak-with-postgres.yaml new file mode 100644 index 000000000..a5cdd1646 --- /dev/null +++ b/templates/compose/keycloak-with-postgres.yaml @@ -0,0 +1,58 @@ +# documentation: https://www.keycloak.org +# slogan: Keycloak is an open-source Identity and Access Management tool. +# tags: keycloak,identity,access,management,iam,authentication,authorization,security,oauth2,openid-connect,sso,single-sign-on,saml,rbac,ldap,jwt,social-login +# logo: svgs/keycloak.svg +# port: 8080 + +services: + keycloak: + image: quay.io/keycloak/keycloak:25.0.2 + command: + - start + environment: + - PUID=1000 + - PGID=1000 + - TZ=Europe/Berlin + - KEYCLOAK_ADMIN=${KEYCLOAK_ADMIN:-admin} + - KEYCLOAK_ADMIN_PASSWORD=${KEYCLOAK_ADMIN_PASSWORD:-password} + - KC_DB=postgres + - KC_DB_USERNAME=${SERVICE_USER_DATABASE} + - KC_DB_PASSWORD=${SERVICE_PASSWORD_64_DATABASE} + - KC_DB_URL_PORT=5432 + - KC_DB_URL=jdbc:postgresql://postgres/${POSTGRESQL_DATABASE:-keycloak} + - KC_HOSTNAME=${SERVICE_FQDN_KEYCLOAK_8080} + - KC_ENABLE_HTTPS=false + - KC_HTTP_ENABLED=true + - KC_HEALTH_ENABLED=true + - KC_DB_POOL_INITIAL_SIZE=${KEYCLOAK_DB_POOL_INITIAL_SIZE} + - KC_DB_POOL_MIN_SIZE=${KEYCLOAK_DB_POOL_MIN_SIZE:-0} + - KC_DB_POOL_MAX_SIZE=${KEYCLOAK_DB_POOL_MAX_SIZE:-100} + - KC_METRICS_ENABLED=${KEYCLOAK_METRICS_ENABLED:-false} + - KC_DIR=${KEYCLOAK_DIR} + - KC_FILE=${KEYCLOAK_FILE} + - KC_OVERRIDE=${KEYCLOAK_OVERRIDE:-true} + volumes: + - keycloak-data:/opt/keycloak/data + depends_on: + postgres: + condition: service_healthy + healthcheck: + test: ["CMD-SHELL", "exec 3<>/dev/tcp/127.0.0.1/9000;echo -e 'GET /health/ready HTTP/1.1\r\nhost: http://localhost\r\nConnection: close\r\n\r\n' >&3;if [ $? -eq 0 ]; then echo 'Healthcheck Successful';exit 0;else echo 'Healthcheck Failed';exit 1;fi;"] + interval: 5s + timeout: 20s + retries: 10 + postgres: + image: postgres:16-alpine + volumes: + - postgresql-data:/var/lib/postgresql/data + environment: + - POSTGRES_USER=${SERVICE_USER_DATABASE} + - POSTGRES_PASSWORD=${SERVICE_PASSWORD_64_DATABASE} + - POSTGRES_DB=${POSTGRESQL_DATABASE:-keycloak} + healthcheck: + test: + - CMD-SHELL + - pg_isready -U $${SERVICE_USER_DATABASE} -d $${POSTGRESQL_DATABASE} + interval: 5s + timeout: 20s + retries: 10 diff --git a/templates/compose/keycloak.yaml b/templates/compose/keycloak.yaml new file mode 100644 index 000000000..388d24d5b --- /dev/null +++ b/templates/compose/keycloak.yaml @@ -0,0 +1,35 @@ +# documentation: https://www.keycloak.org +# slogan: Keycloak is an open-source Identity and Access Management tool. +# tags: keycloak,identity,access,management,iam,authentication,authorization,security,oauth2,openid-connect,sso,single-sign-on,saml,rbac,ldap,jwt,social-login +# logo: svgs/keycloak.svg +# port: 8080 + +services: + keycloak: + image: quay.io/keycloak/keycloak:25.0.2 + command: + - start + environment: + - PUID=1000 + - PGID=1000 + - TZ=Europe/Berlin + - KEYCLOAK_ADMIN=${KEYCLOAK_ADMIN:-admin} + - KEYCLOAK_ADMIN_PASSWORD=${KEYCLOAK_ADMIN_PASSWORD:-password} + - KC_HOSTNAME=${SERVICE_FQDN_KEYCLOAK_8080} + - KC_ENABLE_HTTPS=false + - KC_HTTP_ENABLED=true + - KC_HEALTH_ENABLED=true + - KC_DB_POOL_INITIAL_SIZE=${KEYCLOAK_DB_POOL_INITIAL_SIZE} + - KC_DB_POOL_MIN_SIZE=${KEYCLOAK_DB_POOL_MIN_SIZE:-0} + - KC_DB_POOL_MAX_SIZE=${KEYCLOAK_DB_POOL_MAX_SIZE:-100} + - KC_METRICS_ENABLED=${KEYCLOAK_METRICS_ENABLED:-false} + - KC_DIR=${KEYCLOAK_DIR} + - KC_FILE=${KEYCLOAK_FILE} + - KC_OVERRIDE=${KEYCLOAK_OVERRIDE:-true} + volumes: + - keycloak-data:/opt/keycloak/data + healthcheck: + test: ["CMD-SHELL", "exec 3<>/dev/tcp/127.0.0.1/9000;echo -e 'GET /health/ready HTTP/1.1\r\nhost: http://localhost\r\nConnection: close\r\n\r\n' >&3;if [ $? -eq 0 ]; then echo 'Healthcheck Successful';exit 0;else echo 'Healthcheck Failed';exit 1;fi;"] + interval: 5s + timeout: 20s + retries: 10 From ae5e720b473f536c43a7faeeb0a876fd1644a24b Mon Sep 17 00:00:00 2001 From: christiankolbow Date: Sat, 17 Aug 2024 16:39:05 +0200 Subject: [PATCH 063/863] feat: add zipline template --- templates/compose/zipline.yaml | 41 ++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 templates/compose/zipline.yaml diff --git a/templates/compose/zipline.yaml b/templates/compose/zipline.yaml new file mode 100644 index 000000000..0064c69c5 --- /dev/null +++ b/templates/compose/zipline.yaml @@ -0,0 +1,41 @@ +# documentation: https://github.com/diced/zipline +# slogan: A ShareX/file upload server that is easy to use, packed with features, and with an easy setup! +# tags: zipline,file-sharing,upload,sharing +# port: 3000 +services: + zipline: + image: ghcr.io/diced/zipline + restart: unless-stopped + environment: + - SERVICE_FQDN_ZIPLINE_3000 + - CORE_RETURN_HTTPS=false + - CORE_SECRET=${SERVICE_PASSWORD_64_ZIPLINE} + - CORE_DATABASE_URL=postgres://${SERVICE_USER_DATABASE}:${SERVICE_PASSWORD_64_DATABASE}@postgres/${POSTGRESQL_DATABASE:-zipline} + - CORE_LOGGER=true + volumes: + - zipline-uploads:/zipline/uploads + - zipline-public:/zipline/public + depends_on: + postgres: + condition: service_healthy + healthcheck: + test: + ["CMD", "wget", "-q", "--spider", "http://127.0.0.1:3000/auth/login"] + interval: 5s + timeout: 20s + retries: 10 + postgres: + image: postgres:16-alpine + volumes: + - postgresql-data:/var/lib/postgresql/data + environment: + - POSTGRES_USER=${SERVICE_USER_DATABASE} + - POSTGRES_PASSWORD=${SERVICE_PASSWORD_64_DATABASE} + - POSTGRES_DB=${POSTGRESQL_DATABASE:-zipline} + healthcheck: + test: + - CMD-SHELL + - pg_isready -U $${SERVICE_USER_DATABASE} -d $${POSTGRESQL_DATABASE} + interval: 5s + timeout: 20s + retries: 10 From 2f356b16b66d15d65d108353094a5179243ce4e9 Mon Sep 17 00:00:00 2001 From: christiankolbow Date: Sat, 17 Aug 2024 16:41:21 +0200 Subject: [PATCH 064/863] feat: add onedev template --- public/svgs/onedev.svg | 51 +++++++++++++++++++++++++++++++++++ templates/compose/onedev.yaml | 41 ++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 public/svgs/onedev.svg create mode 100644 templates/compose/onedev.yaml diff --git a/public/svgs/onedev.svg b/public/svgs/onedev.svg new file mode 100644 index 000000000..fb9c9c060 --- /dev/null +++ b/public/svgs/onedev.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + diff --git a/templates/compose/onedev.yaml b/templates/compose/onedev.yaml new file mode 100644 index 000000000..87e719daf --- /dev/null +++ b/templates/compose/onedev.yaml @@ -0,0 +1,41 @@ +# documentation: https://docs.onedev.io/ +# slogan: Git server with CI/CD, kanban, and packages. Seamless integration. Unparalleled experience. +# tags: git, scm, ci, cd, kanban, packages, devops, collaboration, code, repository, management +# logo: svgs/onedev.svg +# port: 6610 +services: + onedev-app: + image: 1dev/server:latest + volumes: + - onedev-docker-sock:/var/run/docker.sock + - onedev-data:/opt/onedev + restart: unless-stopped + environment: + - hibernate_dialect=io.onedev.server.persistence.PostgreSQLDialect + - hibernate_connection_driver_class=org.postgresql.Driver + - hibernate_connection_url=jdbc:postgresql://postgres:5432/${POSTGRESQL_DATABASE:-onedev} + - hibernate_connection_username=${SERVICE_USER_DATABASE} + - hibernate_connection_password=${SERVICE_PASSWORD_64_DATABASE} + - initial_user=${SERVICE_USER_ONEDEV} + - initial_password=${SERVICE_PASSWORD_ONEDEV} + - initial_email=${ONEDEV_EMAIL:-mail@example.com} + - initial_server_url=${SERVICE_FQDN_ONEDEV_6610} + - initial_ssh_root_url=${SSH_ROOT_URL:-ssh://changeme:22} + depends_on: + postgres: + condition: service_healthy + healthcheck: + test: ["CMD", "true"] + postgres: + image: postgres:16-alpine + volumes: + - postgresql-data:/var/lib/postgresql/data + environment: + - POSTGRES_USER=${SERVICE_USER_DATABASE} + - POSTGRES_PASSWORD=${SERVICE_PASSWORD_64_DATABASE} + - POSTGRES_DB=${POSTGRESQL_DATABASE:-onedev} + healthcheck: + test: ["CMD-SHELL", "pg_isready"] + interval: 5s + timeout: 20s + retries: 10 \ No newline at end of file From 1653fcbddc1ea82275b5a1b17238a1216fa90264 Mon Sep 17 00:00:00 2001 From: christiankolbow Date: Sun, 18 Aug 2024 11:58:55 +0200 Subject: [PATCH 065/863] feat: add ntfy template --- public/svgs/ntfy.svg | 1 + templates/compose/ntfy.yaml | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 public/svgs/ntfy.svg create mode 100644 templates/compose/ntfy.yaml diff --git a/public/svgs/ntfy.svg b/public/svgs/ntfy.svg new file mode 100644 index 000000000..9e5b5136f --- /dev/null +++ b/public/svgs/ntfy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/compose/ntfy.yaml b/templates/compose/ntfy.yaml new file mode 100644 index 000000000..ec8c39d28 --- /dev/null +++ b/templates/compose/ntfy.yaml @@ -0,0 +1,26 @@ +# documentation: https://docs.ntfy.sh/ +# slogan: ntfy is a simple HTTP-based pub-sub notification service. It allows you to send notifications to your phone or desktop via scripts from any computer, and/or using a REST API. +# tags: ntfy, notification, push notification, pub-sub, notify +# logo: svgs/ntfy.svg +# port: 80 + +services: + ntfy: + image: binwiederhier/ntfy + container_name: ntfy + command: + - serve + environment: + - SERVICE_FQDN_NTFY + - TZ=Europe/Berlin + user: 1000:1000 + volumes: + - ntfy-cache:/var/cache/ntfy + - ntfy:/etc/ntfy + healthcheck: + test: ["CMD-SHELL", "wget -q --tries=1 http://localhost:80/v1/health -O - | grep -Eo '\"healthy\"\\s*:\\s*true' || exit 1"] + interval: 60s + timeout: 10s + retries: 3 + start_period: 40s + restart: unless-stopped From dfb9081d4e9db3d93106dcefadadf2ea1030c26f Mon Sep 17 00:00:00 2001 From: Sylvain Autran Date: Sun, 18 Aug 2024 12:32:20 +0200 Subject: [PATCH 066/863] Add traccar to service templates --- templates/compose/traccar.yml | 48 +++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 templates/compose/traccar.yml diff --git a/templates/compose/traccar.yml b/templates/compose/traccar.yml new file mode 100644 index 000000000..d22385a75 --- /dev/null +++ b/templates/compose/traccar.yml @@ -0,0 +1,48 @@ +# documentation: https://www.traccar.org/documentation/ +# slogan: Traccar is a free and open source modern GPS tracking system. +# tags: traccar,gps,tracking,open,source +# logo: +# port: 8082 + +services: + traccar: + image: traccar/traccar + environment: + - SERVICE_FQDN_TRACCAR_8082 + - SERVICE_FQDN_TRACCAR_5159=/api + - CONFIG_USE_ENVIRONMENT_VARIABLES=true + - DATABASE_USER=$SERVICE_USER_POSTGRES + - DATABASE_PASSWORD=$SERVICE_PASSWORD_POSTGRES + volumes: + - type: bind + source: ./srv/traccar/conf/traccar.xml + target: /opt/traccar/conf/traccar.xml + content: | + + + + ./conf/default.xml + org.postgresql.Driver + jdbc:postgresql://postgres:5432/traccar + + healthcheck: + test: ["CMD", "curl", "-f", "http://127.0.0.1:8082"] + interval: 5s + timeout: 20s + retries: 10 + depends_on: + postgres: + condition: service_healthy + postgres: + image: postgres:16-alpine + environment: + - POSTGRES_USER=$SERVICE_USER_POSTGRES + - POSTGRES_PASSWORD=$SERVICE_PASSWORD_POSTGRES + - POSTGRES_DB=traccar + volumes: + - traccar-db-data:/var/lib/postgresql/data/ + healthcheck: + test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"] + interval: 5s + timeout: 20s + retries: 10 From fd4316e2ed29bb9d6b44ce78d091d9ad3b3f22d1 Mon Sep 17 00:00:00 2001 From: Sylvain Autran Date: Sun, 18 Aug 2024 13:10:19 +0200 Subject: [PATCH 067/863] Update traccar.yml --- templates/compose/traccar.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/templates/compose/traccar.yml b/templates/compose/traccar.yml index d22385a75..00ba1b699 100644 --- a/templates/compose/traccar.yml +++ b/templates/compose/traccar.yml @@ -9,7 +9,7 @@ services: image: traccar/traccar environment: - SERVICE_FQDN_TRACCAR_8082 - - SERVICE_FQDN_TRACCAR_5159=/api + - SERVICE_FQDN_TRACCAR_API_5159 - CONFIG_USE_ENVIRONMENT_VARIABLES=true - DATABASE_USER=$SERVICE_USER_POSTGRES - DATABASE_PASSWORD=$SERVICE_PASSWORD_POSTGRES @@ -25,11 +25,6 @@ services: org.postgresql.Driver jdbc:postgresql://postgres:5432/traccar - healthcheck: - test: ["CMD", "curl", "-f", "http://127.0.0.1:8082"] - interval: 5s - timeout: 20s - retries: 10 depends_on: postgres: condition: service_healthy From 58831b89925b4d5cf26c46fb6324bce2e4059e00 Mon Sep 17 00:00:00 2001 From: christiankolbow Date: Sun, 18 Aug 2024 14:11:24 +0200 Subject: [PATCH 068/863] fix: signup --- templates/compose/ntfy.yaml | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/templates/compose/ntfy.yaml b/templates/compose/ntfy.yaml index ec8c39d28..850238427 100644 --- a/templates/compose/ntfy.yaml +++ b/templates/compose/ntfy.yaml @@ -11,14 +11,39 @@ services: command: - serve environment: - - SERVICE_FQDN_NTFY - - TZ=Europe/Berlin - user: 1000:1000 + - TZ=${TZ:-UTC} + - 'NTFY_BASE_URL=${SERVICE_FQDN_NTFY}' + - NTFY_CACHE_FILE=/var/cache/ntfy/cache.db + - NTFY_AUTH_FILE=/var/lib/ntfy/auth.db + - NTFY_AUTH_DEFAULT_ACCESS=read-write + - 'NTFY_UPSTREAM_BASE_URL=https://ntfy.sh' + - NTFY_ENABLE_SIGNUP=${NTFY_ENABLE_SIGNUP:-true} + - NTFY_ENABLE_LOGIN=${NTFY_ENABLE_LOGIN:-true} + - NTFY_CACHE_DURATION=${NTFY_CACHE_DURATION:-24h} + - NTFY_ATTACHMENT_TOTAL_SIZE_LIMIT=${NTFY_ATTACHMENT_TOTAL_SIZE_LIMIT:-1G} + - NTFY_ATTACHMENT_FILE_SIZE_LIMIT=${NTFY_ATTACHMENT_FILE_SIZE_LIMIT:-10M} + - NTFY_ATTACHMENT_EXPIRY_DURATION=${NTFY_ATTACHMENT_EXPIRY_DURATION:-24h} + - NTFY_SMTP_SENDER_ADDR=${NTFY_SMTP_SENDER_ADDR:-smtp.deine-domain.de} + - NTFY_SMTP_SENDER_USER=${NTFY_SMTP_SENDER_USER:-no-reply@de} + - NTFY_SMTP_SENDER_PASS=${NTFY_SMTP_SENDER_PASS:-password} + - NTFY_SMTP_SENDER_FROM=${NTFY_SMTP_SENDER_FROM:-no-reply@de} + - NTFY_KEEPALIVE_INTERVAL=${NTFY_KEEPALIVE_INTERVAL:-5m} + - NTFY_MANAGER_INTERVAL=${NTFY_MANAGER_INTERVAL:-5m} + - NTFY_VISITOR_MESSAGE_DAILY_LIMIT=${NTFY_VISITOR_MESSAGE_DAILY_LIMIT:-100} + - NTFY_VISITOR_ATTACHMENT_DAILY_BANDWIDTH_LIMIT=${NTFY_VISITOR_ATTACHMENT_DAILY_BANDWIDTH_LIMIT:-1G} + - NTFY_UPSTREAM_BASE_URL=${SERVICE_FQDN_NTFY} + - NTFY_UPSTREAM_ACCESS_TOKEN=${UPSTREAM_ACCESS_TOKEN} + - NTFY_AUTH_DEFAULT_ACCESS=${NTFY_AUTH_DEFAULT_ACCESS:-read-write} + - NTFY_WEB_PUSH_PUBLIC_KEY=${NTFY_WEB_PUSH_PUBLIC_KEY} + - NTFY_WEB_PUSH_PRIVATE_KEY=${NTFY_WEB_PUSH_PRIVATE_KEY} + - NTFY_WEB_PUSH_EMAIL_ADDRESS=${NTFY_WEB_PUSH_EMAIL_ADDRESS} volumes: - - ntfy-cache:/var/cache/ntfy - - ntfy:/etc/ntfy + - ./cache:/var/cache/ntfy + - ./db:/var/lib/ntfy/ healthcheck: - test: ["CMD-SHELL", "wget -q --tries=1 http://localhost:80/v1/health -O - | grep -Eo '\"healthy\"\\s*:\\s*true' || exit 1"] + test: + - CMD-SHELL + - 'wget -q --tries=1 http://localhost:80/v1/health -O - | grep -Eo ''"healthy"\s*:\s*true'' || exit 1' interval: 60s timeout: 10s retries: 3 From d5e6a643aaa0b9b3a67be1b556ccd1277f2b70bd Mon Sep 17 00:00:00 2001 From: christiankolbow Date: Sun, 18 Aug 2024 14:16:14 +0200 Subject: [PATCH 069/863] cleanup --- templates/compose/ntfy.yaml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/templates/compose/ntfy.yaml b/templates/compose/ntfy.yaml index 850238427..06187a368 100644 --- a/templates/compose/ntfy.yaml +++ b/templates/compose/ntfy.yaml @@ -12,11 +12,11 @@ services: - serve environment: - TZ=${TZ:-UTC} - - 'NTFY_BASE_URL=${SERVICE_FQDN_NTFY}' + - NTFY_BASE_URL=${SERVICE_FQDN_NTFY} - NTFY_CACHE_FILE=/var/cache/ntfy/cache.db - NTFY_AUTH_FILE=/var/lib/ntfy/auth.db - NTFY_AUTH_DEFAULT_ACCESS=read-write - - 'NTFY_UPSTREAM_BASE_URL=https://ntfy.sh' + - NTFY_UPSTREAM_BASE_URL=${UPSTREAM_BASE_URL:-https://ntfy.sh} - NTFY_ENABLE_SIGNUP=${NTFY_ENABLE_SIGNUP:-true} - NTFY_ENABLE_LOGIN=${NTFY_ENABLE_LOGIN:-true} - NTFY_CACHE_DURATION=${NTFY_CACHE_DURATION:-24h} @@ -41,9 +41,7 @@ services: - ./cache:/var/cache/ntfy - ./db:/var/lib/ntfy/ healthcheck: - test: - - CMD-SHELL - - 'wget -q --tries=1 http://localhost:80/v1/health -O - | grep -Eo ''"healthy"\s*:\s*true'' || exit 1' + test: ["CMD-SHELL", "wget -q --tries=1 http://localhost:80/v1/health -O - | grep -Eo '\"healthy\"\\s*:\\s*true' || exit 1"] interval: 60s timeout: 10s retries: 3 From 2fc0ce172050e530b415463d15eccbfab8e68ff5 Mon Sep 17 00:00:00 2001 From: christiankolbow Date: Sun, 18 Aug 2024 14:18:07 +0200 Subject: [PATCH 070/863] remove duplicated env --- templates/compose/ntfy.yaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/templates/compose/ntfy.yaml b/templates/compose/ntfy.yaml index 06187a368..3914136a5 100644 --- a/templates/compose/ntfy.yaml +++ b/templates/compose/ntfy.yaml @@ -15,7 +15,6 @@ services: - NTFY_BASE_URL=${SERVICE_FQDN_NTFY} - NTFY_CACHE_FILE=/var/cache/ntfy/cache.db - NTFY_AUTH_FILE=/var/lib/ntfy/auth.db - - NTFY_AUTH_DEFAULT_ACCESS=read-write - NTFY_UPSTREAM_BASE_URL=${UPSTREAM_BASE_URL:-https://ntfy.sh} - NTFY_ENABLE_SIGNUP=${NTFY_ENABLE_SIGNUP:-true} - NTFY_ENABLE_LOGIN=${NTFY_ENABLE_LOGIN:-true} @@ -23,7 +22,7 @@ services: - NTFY_ATTACHMENT_TOTAL_SIZE_LIMIT=${NTFY_ATTACHMENT_TOTAL_SIZE_LIMIT:-1G} - NTFY_ATTACHMENT_FILE_SIZE_LIMIT=${NTFY_ATTACHMENT_FILE_SIZE_LIMIT:-10M} - NTFY_ATTACHMENT_EXPIRY_DURATION=${NTFY_ATTACHMENT_EXPIRY_DURATION:-24h} - - NTFY_SMTP_SENDER_ADDR=${NTFY_SMTP_SENDER_ADDR:-smtp.deine-domain.de} + - NTFY_SMTP_SENDER_ADDR=${NTFY_SMTP_SENDER_ADDR:-smtp.your-domain.de} - NTFY_SMTP_SENDER_USER=${NTFY_SMTP_SENDER_USER:-no-reply@de} - NTFY_SMTP_SENDER_PASS=${NTFY_SMTP_SENDER_PASS:-password} - NTFY_SMTP_SENDER_FROM=${NTFY_SMTP_SENDER_FROM:-no-reply@de} @@ -31,7 +30,6 @@ services: - NTFY_MANAGER_INTERVAL=${NTFY_MANAGER_INTERVAL:-5m} - NTFY_VISITOR_MESSAGE_DAILY_LIMIT=${NTFY_VISITOR_MESSAGE_DAILY_LIMIT:-100} - NTFY_VISITOR_ATTACHMENT_DAILY_BANDWIDTH_LIMIT=${NTFY_VISITOR_ATTACHMENT_DAILY_BANDWIDTH_LIMIT:-1G} - - NTFY_UPSTREAM_BASE_URL=${SERVICE_FQDN_NTFY} - NTFY_UPSTREAM_ACCESS_TOKEN=${UPSTREAM_ACCESS_TOKEN} - NTFY_AUTH_DEFAULT_ACCESS=${NTFY_AUTH_DEFAULT_ACCESS:-read-write} - NTFY_WEB_PUSH_PUBLIC_KEY=${NTFY_WEB_PUSH_PUBLIC_KEY} From e1bcae7aafb83563e1b34aceef5d15d079c2211d Mon Sep 17 00:00:00 2001 From: 8x4 <46720448+8times4@users.noreply.github.com> Date: Mon, 19 Aug 2024 15:50:57 +0200 Subject: [PATCH 071/863] add resend.yaml --- templates/compose/resend.yaml | 63 +++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 templates/compose/resend.yaml diff --git a/templates/compose/resend.yaml b/templates/compose/resend.yaml new file mode 100644 index 000000000..d72228747 --- /dev/null +++ b/templates/compose/resend.yaml @@ -0,0 +1,63 @@ +# documentation: https://docs.unsend.dev/get-started/self-hosting +# slogan: Unsend is an open-source alternative to Resend, Sendgrid, Mailgun and Postmark etc. +# tags: resend, mailer, marketing emails, transaction emails, self-hosting, postmark +# logo: svgs/unsend.svg +# port: 3000 + +services: + postgres: + image: postgres:16 + container_name: unsend-db-prod + restart: always + environment: + - POSTGRES_USER=${SERVICE_POSTGRES_USER:?err} + - POSTGRES_PASSWORD=${SERVICE_POSTGRES_PASSWORD:?err} + - POSTGRES_DB=${SERVICE_POSTGRES_DB:?err} + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"] + interval: 10s + timeout: 5s + retries: 5 + # ports: + # - "5432:5432" + volumes: + - unsend-db:/var/lib/postgresql/data + + redis: + image: redis:7 + container_name: unsend-redis-prod + restart: always + # ports: + # - "6379:6379" + volumes: + - unsend-cache:/data + command: ["redis-server", "--maxmemory-policy", "noeviction"] + + unsend: + image: unsend/unsend:latest + container_name: unsend + restart: always + ports: + - ${PORT:-3000}:${PORT:-3000} + environment: + - PORT=${PORT:-3000} + - DATABASE_URL=postgresql://postgres:${SERVICE_POSTGRES_PASSWORD}@postgres:5432/resend + - NEXTAUTH_URL=${SERVICE_NEXTAUTH_URL:?err} + - NEXTAUTH_SECRET=${SERVICE_NEXTAUTH_SECRET:?err} + - AWS_ACCESS_KEY=${SERVICE_AWS_ACCESS_KEY:?err} + - AWS_SECRET_KEY=${SERVICE_AWS_SECRET_KEY:?err} + - AWS_DEFAULT_REGION=${SERVICE_AWS_DEFAULT_REGION:?err} + - GITHUB_ID=${SERVICE_GITHUB_ID:?err} + - GITHUB_SECRET=${SERVICE_GITHUB_SECRET:?err} + - REDIS_URL=redis://redis:6379 + - NEXT_PUBLIC_IS_CLOUD=${NEXT_PUBLIC_IS_CLOUD:-false} + - API_RATE_LIMIT=${SERVICE_API_RATE_LIMIT:-1} + depends_on: + postgres: + condition: service_healthy + redis: + condition: service_started + +volumes: + unsend-db: + unsend-cache: From 4b14c7e2205fab9fdcbf7673be301cb9d0a2dc57 Mon Sep 17 00:00:00 2001 From: 8x4 <46720448+8times4@users.noreply.github.com> Date: Mon, 19 Aug 2024 15:52:11 +0200 Subject: [PATCH 072/863] remove comments --- templates/compose/resend.yaml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/templates/compose/resend.yaml b/templates/compose/resend.yaml index d72228747..b8b528a75 100644 --- a/templates/compose/resend.yaml +++ b/templates/compose/resend.yaml @@ -18,8 +18,6 @@ services: interval: 10s timeout: 5s retries: 5 - # ports: - # - "5432:5432" volumes: - unsend-db:/var/lib/postgresql/data @@ -27,8 +25,6 @@ services: image: redis:7 container_name: unsend-redis-prod restart: always - # ports: - # - "6379:6379" volumes: - unsend-cache:/data command: ["redis-server", "--maxmemory-policy", "noeviction"] From cf99ec70e9a19487176e614e55bf2233bcbabb45 Mon Sep 17 00:00:00 2001 From: 8x4 <46720448+8times4@users.noreply.github.com> Date: Mon, 19 Aug 2024 15:52:31 +0200 Subject: [PATCH 073/863] add svg --- public/svgs/unsend.svg | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 public/svgs/unsend.svg diff --git a/public/svgs/unsend.svg b/public/svgs/unsend.svg new file mode 100644 index 000000000..f5ff6fabc --- /dev/null +++ b/public/svgs/unsend.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + From 1e46b6304138369be0ada20489492f8708eb2572 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Tue, 20 Aug 2024 18:32:35 +0200 Subject: [PATCH 074/863] Feat getoutline service --- public/svgs/getoutline.jpeg | Bin 0 -> 5651 bytes templates/compose/getoutline.yaml | 92 ++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 public/svgs/getoutline.jpeg create mode 100644 templates/compose/getoutline.yaml diff --git a/public/svgs/getoutline.jpeg b/public/svgs/getoutline.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..422e402f7e1351c864b55a619417ab2b5faab0c8 GIT binary patch literal 5651 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 tJ Date: Thu, 22 Aug 2024 16:38:36 +0200 Subject: [PATCH 075/863] feat: add cloudbeaver template --- public/svgs/cloudbeaver.svg | 7 +++++++ templates/compose/cloudbeaver.yaml | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 public/svgs/cloudbeaver.svg create mode 100644 templates/compose/cloudbeaver.yaml diff --git a/public/svgs/cloudbeaver.svg b/public/svgs/cloudbeaver.svg new file mode 100644 index 000000000..4a7634766 --- /dev/null +++ b/public/svgs/cloudbeaver.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/templates/compose/cloudbeaver.yaml b/templates/compose/cloudbeaver.yaml new file mode 100644 index 000000000..6ca82eecf --- /dev/null +++ b/templates/compose/cloudbeaver.yaml @@ -0,0 +1,18 @@ +# documentation: https://dbeaver.com/docs/cloudbeaver/ +# slogan: CloudBeaver is a lightweight web application designed for comprehensive data management. +# tags: dbeaver, data management, data, database, mysql, postgres, sqlite, sql, mongodb +# logo: svgs/cloudbeaver.svg + +services: + cloudbeaver: + restart: unless-stopped + image: dbeaver/cloudbeaver:24.1.5 + volumes: + - cloudbeaver:/opt/cloudbeaver/workspace + environment: + - SERVICE_FQDN_CLOUDBEAVER_8978 + healthcheck: + test: ["CMD", "wget", "-q", "--spider", "http://127.0.0.1:8978/"] + interval: 5s + timeout: 20s + retries: 10 From c1eb01fac596a9234dede2d5620208cce56952bb Mon Sep 17 00:00:00 2001 From: Franck Kerbiriou Date: Thu, 22 Aug 2024 22:21:13 +0200 Subject: [PATCH 076/863] Upgrade Authentik --- templates/compose/authentik.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/templates/compose/authentik.yaml b/templates/compose/authentik.yaml index 4fa7a7617..5fdc216e5 100644 --- a/templates/compose/authentik.yaml +++ b/templates/compose/authentik.yaml @@ -6,7 +6,7 @@ services: postgresql: - image: docker.io/library/postgres:12-alpine + image: docker.io/library/postgres:16-alpine restart: unless-stopped healthcheck: test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"] @@ -31,7 +31,7 @@ services: volumes: - redis:/data authentik-server: - image: ghcr.io/goauthentik/server:${AUTHENTIK_TAG:-2024.2.2} + image: ghcr.io/goauthentik/server:${AUTHENTIK_TAG:-2024.6.3} restart: unless-stopped command: server environment: @@ -60,7 +60,7 @@ services: redis: condition: service_healthy authentik-worker: - image: ghcr.io/goauthentik/server:${AUTHENTIK_TAG:-2024.2.2} + image: ghcr.io/goauthentik/server:${AUTHENTIK_TAG:-2024.6.3} restart: unless-stopped command: worker environment: From a4dedb8369adb040259bbeae3b46e12aaa0957e1 Mon Sep 17 00:00:00 2001 From: Franck Kerbiriou Date: Thu, 22 Aug 2024 22:30:45 +0200 Subject: [PATCH 077/863] Add Nextcloud with Postgres --- .../compose/nextcloud-with-postgres.yaml | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 templates/compose/nextcloud-with-postgres.yaml diff --git a/templates/compose/nextcloud-with-postgres.yaml b/templates/compose/nextcloud-with-postgres.yaml new file mode 100644 index 000000000..15a2c97b6 --- /dev/null +++ b/templates/compose/nextcloud-with-postgres.yaml @@ -0,0 +1,52 @@ +# documentation: https://docs.nextcloud.com +# slogan: NextCloud is a self-hosted, open-source platform that provides file storage, collaboration, and communication tools for seamless data management. +# tags: cloud, collaboration, communication, filestorage, data +# logo: svgs/nextcloud.svg + +services: + nextcloud: + image: lscr.io/linuxserver/nextcloud:latest + environment: + - SERVICE_FQDN_NEXTCLOUD + - PUID=1000 + - PGID=1000 + - TZ=Europe/Paris + - POSTGRES_DB=${POSTGRES_DB:-nextcloud} + - POSTGRES_USER=$SERVICE_USER_POSTGRES + - POSTGRES_PASSWORD=$SERVICE_PASSWORD_POSTGRES + - POSTGRES_HOST=postgresql + - REDIS_HOST=redis + - REDIS_PORT=6379 + volumes: + - nextcloud-config:/config + - nextcloud-data:/data + healthcheck: + test: ["CMD", "curl", "-f", "http://127.0.0.1:80"] + interval: 2s + timeout: 10s + retries: 15 + postgresql: + image: postgres:16-alpine + volumes: + - postgresql-data:/var/lib/postgresql/data + environment: + - POSTGRES_USER=$SERVICE_USER_POSTGRES + - POSTGRES_PASSWORD=$SERVICE_PASSWORD_POSTGRES + - POSTGRES_DB=${POSTGRES_DB:-nextcloud} + healthcheck: + test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"] + interval: 5s + timeout: 20s + retries: 10 + redis: + image: "redis:7.4-alpine" + volumes: + - "redis-data:/data" + healthcheck: + test: + - CMD + - redis-cli + - PING + interval: 5s + timeout: 10s + retries: 20 From 7e154ba3c38926e607e6d28f09fa09d4d72b8a79 Mon Sep 17 00:00:00 2001 From: Franck Kerbiriou Date: Thu, 22 Aug 2024 22:52:20 +0200 Subject: [PATCH 078/863] Add Mailpit template --- public/svgs/mailpit.svg | 5 +++++ templates/compose/mailpit.yaml | 20 ++++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 public/svgs/mailpit.svg create mode 100644 templates/compose/mailpit.yaml diff --git a/public/svgs/mailpit.svg b/public/svgs/mailpit.svg new file mode 100644 index 000000000..e569e71cc --- /dev/null +++ b/public/svgs/mailpit.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/templates/compose/mailpit.yaml b/templates/compose/mailpit.yaml new file mode 100644 index 000000000..46072fb21 --- /dev/null +++ b/templates/compose/mailpit.yaml @@ -0,0 +1,20 @@ +# documentation: https://mailpit.axllent.org/docs/ +# slogan: Email & SMTP testing tool with API for developers +# tags: mailpit,email,testing,smtp +# logo: svgs/mailpit.png +# port: 8025 + +services: + mailpit: + image: axllent/mailpit + container_name: mailpit + volumes: + - "mailpit-data:/data" + ports: + - "1025:1025" + environment: + - SERVICE_FQDN_MAILPIT_8025 + - MP_MAX_MESSAGES: 5000 + - MP_DATABASE: /data/mailpit.db + - MP_SMTP_AUTH_ACCEPT_ANY: 1 + - MP_SMTP_AUTH_ALLOW_INSECURE: 1 From 15733eaa55fd1cfc307d3aa359b89e2e88f3bc82 Mon Sep 17 00:00:00 2001 From: Pilpin Date: Sat, 24 Aug 2024 12:49:33 +0200 Subject: [PATCH 079/863] Add freshrss to service templates --- templates/compose/freshrss.yaml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 templates/compose/freshrss.yaml diff --git a/templates/compose/freshrss.yaml b/templates/compose/freshrss.yaml new file mode 100644 index 000000000..607d44a2e --- /dev/null +++ b/templates/compose/freshrss.yaml @@ -0,0 +1,17 @@ +# documentation: https://docs.gitea.com +# slogan: Gitea is a self-hosted, lightweight Git service, offering version control, collaboration, and code hosting. +# tags: version control, collaboration, code, hosting, lightweight, postgresql +# logo: svgs/gitea.svg + +services: + freshrss: + image: freshrss/freshrss:latest + environment: + - SERVICE_FQDN_FRESHRSS_80 + - POSTGRES_DB=freshrss + - POSTGRES_USER=$SERVICE_USER_POSTGRES + - POSTGRES_PASSWORD=$SERVICE_PASSWORD_POSTGRES + - 'CRON_MIN=1,31' + volumes: + - freshrss_data:/var/www/FreshRSS/data + - freshrss_extensions:/var/www/FreshRSS/extensions From 3c720357115aa2bc6ce35c228a1a19c9c11e6dfc Mon Sep 17 00:00:00 2001 From: Sylvain Autran Date: Sun, 25 Aug 2024 00:06:22 +0200 Subject: [PATCH 080/863] Update documentation part of yaml --- templates/compose/freshrss.yaml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/templates/compose/freshrss.yaml b/templates/compose/freshrss.yaml index 607d44a2e..1c5eb0ce4 100644 --- a/templates/compose/freshrss.yaml +++ b/templates/compose/freshrss.yaml @@ -1,7 +1,6 @@ -# documentation: https://docs.gitea.com -# slogan: Gitea is a self-hosted, lightweight Git service, offering version control, collaboration, and code hosting. -# tags: version control, collaboration, code, hosting, lightweight, postgresql -# logo: svgs/gitea.svg +# documentation: https://freshrss.org/index.html +# slogan: A free, self-hostable feed aggregator. +# tags: rss, feed services: freshrss: From 135eb83da454d59178d48d8dbeff949b26fd561d Mon Sep 17 00:00:00 2001 From: givanz Date: Sun, 25 Aug 2024 16:27:02 +0300 Subject: [PATCH 081/863] Add Vvveb CMS template --- public/svgs/vvveb.svg | 1 + templates/compose/vvveb-with-mariadb.yml | 38 ++++++++++++++++++++ templates/compose/vvveb-without-database.yml | 18 ++++++++++ templates/compose/vvveb.yml | 38 ++++++++++++++++++++ 4 files changed, 95 insertions(+) create mode 100644 public/svgs/vvveb.svg create mode 100644 templates/compose/vvveb-with-mariadb.yml create mode 100644 templates/compose/vvveb-without-database.yml create mode 100644 templates/compose/vvveb.yml diff --git a/public/svgs/vvveb.svg b/public/svgs/vvveb.svg new file mode 100644 index 000000000..2b66b3087 --- /dev/null +++ b/public/svgs/vvveb.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/compose/vvveb-with-mariadb.yml b/templates/compose/vvveb-with-mariadb.yml new file mode 100644 index 000000000..7e1d663fa --- /dev/null +++ b/templates/compose/vvveb-with-mariadb.yml @@ -0,0 +1,38 @@ +# documentation: https://docs.vvveb.com +# slogan: Powerful and easy to use cms to build websites, blogs or ecommerce stores. +# tags: cms, blog, content, management, ecommerce, page-builder, nocode, mysql, sqlite, pgsql +# logo: svgs/vvveb.svg + +services: + vvveb: + image: vvveb/vvvebcms:latest + volumes: + - vvveb-files:/var/www/html + environment: + - SERVICE_FQDN_VVVEB + - DB_ENGINE=mysqli #sqlite,pgsql + - DB_HOST=mariadb + - DB_USER=$SERVICE_USER_VVVEB + - DB_PASSWORD=$SERVICE_PASSWORD_VVVEB + - DB_NAME=vvveb + depends_on: + - mariadb + healthcheck: + test: ["CMD", "curl", "-f", "http://127.0.0.1"] + interval: 2s + timeout: 10s + retries: 10 + mariadb: + image: mariadb:11 + volumes: + - mariadb-data:/var/lib/mysql + environment: + - MYSQL_ROOT_PASSWORD=$SERVICE_PASSWORD_ROOT + - MYSQL_DATABASE=vvveb + - MYSQL_USER=$SERVICE_USER_VVVEB + - MYSQL_PASSWORD=$SERVICE_PASSWORD_VVVEB + healthcheck: + test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"] + interval: 5s + timeout: 20s + retries: 10 diff --git a/templates/compose/vvveb-without-database.yml b/templates/compose/vvveb-without-database.yml new file mode 100644 index 000000000..f1e92de63 --- /dev/null +++ b/templates/compose/vvveb-without-database.yml @@ -0,0 +1,18 @@ +# documentation: https://docs.vvveb.com +# slogan: Powerful and easy to use cms to build websites, blogs or ecommerce stores. +# tags: cms, blog, content, management, ecommerce, page-builder, nocode, mysql, sqlite, pgsql +# logo: svgs/vvveb.svg + +services: + vvveb: + image: vvveb/vvvebcms:latest + volumes: + - vvveb-files:/var/www/html + environment: + - SERVICE_FQDN_VVVEB + - DB_ENGINE=sqlite #mysqli,pgsql + healthcheck: + test: ["CMD", "curl", "-f", "http://127.0.0.1"] + interval: 2s + timeout: 10s + retries: 10 diff --git a/templates/compose/vvveb.yml b/templates/compose/vvveb.yml new file mode 100644 index 000000000..43ec27c1a --- /dev/null +++ b/templates/compose/vvveb.yml @@ -0,0 +1,38 @@ +# documentation: https://docs.vvveb.com +# slogan: Powerful and easy to use cms to build websites, blogs or ecommerce stores. +# tags: cms, blog, content, management, ecommerce, page-builder, nocode, mysql, sqlite, pgsql +# logo: svgs/vvveb.svg + +services: + vvveb: + image: vvveb/vvvebcms:latest + volumes: + - vvveb-files:/var/www/html + environment: + - SERVICE_FQDN_VVVEB + - DB_ENGINE=mysqli #sqlite,pgsql + - DB_HOST=mysql + - DB_USER=$SERVICE_USER_VVVEB + - DB_PASSWORD=$SERVICE_PASSWORD_VVVEB + - DB_NAME=vvveb + depends_on: + - mysql + healthcheck: + test: ["CMD", "curl", "-f", "http://127.0.0.1"] + interval: 2s + timeout: 10s + retries: 10 + mysql: + image: mysql:8.4.2 + volumes: + - mysql-data:/var/lib/mysql + environment: + - MYSQL_ROOT_PASSWORD=$SERVICE_PASSWORD_ROOT + - MYSQL_DATABASE=vvveb + - MYSQL_USER=$SERVICE_USER_VVVEB + - MYSQL_PASSWORD=$SERVICE_PASSWORD_VVVEB + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1"] + interval: 5s + timeout: 20s + retries: 10 From 2a581147aa72c56aae32c731f0f51c81eb8d1e6e Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Tue, 27 Aug 2024 12:43:59 +0200 Subject: [PATCH 082/863] new confirm delete dialog --- .../components/modal-confirmation.blade.php | 109 ++++-------------- .../livewire/project/shared/danger.blade.php | 72 ++++++++++-- 2 files changed, 86 insertions(+), 95 deletions(-) diff --git a/resources/views/components/modal-confirmation.blade.php b/resources/views/components/modal-confirmation.blade.php index 7910d2eb2..56abba71d 100644 --- a/resources/views/components/modal-confirmation.blade.php +++ b/resources/views/components/modal-confirmation.blade.php @@ -1,62 +1,41 @@ @props([ 'title' => 'Are you sure?', 'isErrorButton' => false, - 'buttonTitle' => 'REWRITE THIS BUTTON TITLE PLEASSSSEEEE', + 'buttonTitle' => 'Confirm Action', 'buttonFullWidth' => false, 'customButton' => null, 'disabled' => false, 'action' => 'delete', 'content' => null, ]) -
@if ($customButton) - @if ($buttonFullWidth) - - {{ $customButton }} - - @else - - {{ $customButton }} - - @endif + + {{ $customButton }} + @else @if ($content)
{{ $content }}
@else - @if ($disabled) - @if ($buttonFullWidth) - - {{ $buttonTitle }} - - @else - - {{ $buttonTitle }} - - @endif - @elseif ($isErrorButton) - @if ($buttonFullWidth) - - {{ $buttonTitle }} - - @else - - {{ $buttonTitle }} - - @endif - @else - @if ($buttonFullWidth) - - {{ $buttonTitle }} - - @else - - {{ $buttonTitle }} - - @endif - @endif + + {{ $buttonTitle }} + @endif @endif diff --git a/resources/views/livewire/project/shared/danger.blade.php b/resources/views/livewire/project/shared/danger.blade.php index 1e1365749..1b24d0593 100644 --- a/resources/views/livewire/project/shared/danger.blade.php +++ b/resources/views/livewire/project/shared/danger.blade.php @@ -5,13 +5,69 @@
This will stop your containers, delete all related data, etc. Beware! There is no coming back!
+ -
This resource will be deleted. It is not reversible. Please think - again.

-

Actions

- - - - +
+ +
+
Select the actions you want to perform:
+ + + + +
+ Cancel + + Continue + +
+
+ + +
+ +
The following actions will be performed:
+
    + +
+
Please type DELETE to confirm this destructive action:
+ +
+ Back + + Permanently Delete + +
+
+
-
\ No newline at end of file + From ac50d8b4d8f4c9e34ff300a080825e9383433854 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Tue, 27 Aug 2024 12:57:03 +0200 Subject: [PATCH 083/863] fix styling --- resources/views/livewire/project/shared/danger.blade.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/views/livewire/project/shared/danger.blade.php b/resources/views/livewire/project/shared/danger.blade.php index 1b24d0593..c021208f0 100644 --- a/resources/views/livewire/project/shared/danger.blade.php +++ b/resources/views/livewire/project/shared/danger.blade.php @@ -26,10 +26,10 @@
Cancel Continue @@ -55,7 +55,7 @@
Please type DELETE to confirm this destructive action:
- +
Back Date: Tue, 27 Aug 2024 16:48:30 +0530 Subject: [PATCH 084/863] audiobookshelf added --- public/svgs/audiobookshelf.svg | 25 +++++++++++++++++++++++++ templates/compose/audiobookshelf.yaml | 17 +++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 public/svgs/audiobookshelf.svg create mode 100644 templates/compose/audiobookshelf.yaml diff --git a/public/svgs/audiobookshelf.svg b/public/svgs/audiobookshelf.svg new file mode 100644 index 000000000..d641b765b --- /dev/null +++ b/public/svgs/audiobookshelf.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/templates/compose/audiobookshelf.yaml b/templates/compose/audiobookshelf.yaml new file mode 100644 index 000000000..81915676a --- /dev/null +++ b/templates/compose/audiobookshelf.yaml @@ -0,0 +1,17 @@ +# documentation: https://www.audiobookshelf.org/ +# slogan: Self-hosted audiobook, ebook, and podcast server +# tags: audiobooks, ebooks, podcasts, server, self-hosted +# logo: svgs/audiobookshelf.svg +# port: 80 + +services: + audiobookshelf: + image: ghcr.io/advplyr/audiobookshelf:latest + environment: + - SERVICE_FQDN_AUDIOBOOKSHELF_80 + - TZ=America/Toronto + volumes: + - audiobookshelf-audiobooks:/audiobooks + - audiobookshelf-podcasts:/podcasts + - audiobookshelf-config:/config + - audiobookshelf-metadata:/metadata From 9040f5d2a14227d9a91116376161ebc136872da7 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Tue, 27 Aug 2024 13:44:12 +0200 Subject: [PATCH 085/863] confirm with password --- app/Livewire/Project/Shared/Danger.php | 9 +- .../livewire/project/shared/danger.blade.php | 152 ++++++++++-------- 2 files changed, 93 insertions(+), 68 deletions(-) diff --git a/app/Livewire/Project/Shared/Danger.php b/app/Livewire/Project/Shared/Danger.php index cff1d453a..5a49460da 100644 --- a/app/Livewire/Project/Shared/Danger.php +++ b/app/Livewire/Project/Shared/Danger.php @@ -5,6 +5,8 @@ namespace App\Livewire\Project\Shared; use App\Jobs\DeleteResourceJob; use Livewire\Component; use Visus\Cuid2\Cuid2; +use Illuminate\Support\Facades\Hash; +use Illuminate\Support\Facades\Auth; class Danger extends Component { @@ -32,8 +34,13 @@ class Danger extends Component $this->environmentName = data_get($parameters, 'environment_name'); } - public function delete() + public function delete($selectedActions, $password) { + if (!Hash::check($password, Auth::user()->password)) { + $this->addError('password', 'The provided password is incorrect.'); + return; + } + try { // $this->authorize('delete', $this->resource); $this->resource->delete(); diff --git a/resources/views/livewire/project/shared/danger.blade.php b/resources/views/livewire/project/shared/danger.blade.php index c021208f0..11521a8c6 100644 --- a/resources/views/livewire/project/shared/danger.blade.php +++ b/resources/views/livewire/project/shared/danger.blade.php @@ -1,73 +1,91 @@ -
-

Danger Zone

-
Woah. I hope you know what are you doing.
-

Delete Resource

-
This will stop your containers, delete all related data, etc. Beware! There is no coming - back! -
+
+

Danger Zone

- -
- -
-
Select the actions you want to perform:
- - - - -
- Cancel - - Continue - -
+
+
+
+

Delete Resource

+

Once you delete a resource, there is no going back. Please be certain.

+ +
+ +
+
Select the actions you want to perform:
+ + + + +
+ Cancel + + Continue + +
+
- -
- -
The following actions will be performed:
-
    - -
-
Please type DELETE to confirm this destructive action:
- -
- Back - - Permanently Delete - -
-
+
-
+
From 472667624821eb783db40b7287f54a72015c9fdb Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Tue, 27 Aug 2024 14:19:37 +0200 Subject: [PATCH 086/863] make things more clear --- app/Actions/Service/DeleteService.php | 4 ++-- app/Jobs/DeleteResourceJob.php | 6 ++--- app/Livewire/Project/Shared/Danger.php | 4 ++-- .../components/modal-confirmation.blade.php | 18 ++++++--------- .../livewire/project/shared/danger.blade.php | 22 +++++++++++++------ 5 files changed, 29 insertions(+), 25 deletions(-) diff --git a/app/Actions/Service/DeleteService.php b/app/Actions/Service/DeleteService.php index 238e6b954..93c79383e 100644 --- a/app/Actions/Service/DeleteService.php +++ b/app/Actions/Service/DeleteService.php @@ -10,7 +10,7 @@ class DeleteService { use AsAction; - public function handle(Service $service, bool $deleteConfigurations, bool $deleteVolumes, bool $deleteImages, bool $deleteConnectedNetworks) + public function handle(Service $service, bool $deleteConfigurations, bool $deleteVolumes, bool $dockerCleanup, bool $deleteConnectedNetworks) { try { $server = data_get($service, 'server'); @@ -69,7 +69,7 @@ class DeleteService $service->tags()->detach(); $service->forceDelete(); - if ($deleteImages) { + if ($dockerCleanup) { CleanupDocker::run($server, true); } } diff --git a/app/Jobs/DeleteResourceJob.php b/app/Jobs/DeleteResourceJob.php index b8a8756cb..1ebbf4681 100644 --- a/app/Jobs/DeleteResourceJob.php +++ b/app/Jobs/DeleteResourceJob.php @@ -33,7 +33,7 @@ class DeleteResourceJob implements ShouldBeEncrypted, ShouldQueue public Application|Service|StandalonePostgresql|StandaloneRedis|StandaloneMongodb|StandaloneMysql|StandaloneMariadb|StandaloneKeydb|StandaloneDragonfly|StandaloneClickhouse $resource, public bool $deleteConfigurations, public bool $deleteVolumes, - public bool $deleteImages, + public bool $dockerCleanup, public bool $deleteConnectedNetworks ) { } @@ -60,7 +60,7 @@ class DeleteResourceJob implements ShouldBeEncrypted, ShouldQueue break; case 'service': StopService::run($this->resource, true); - DeleteService::run($this->resource, $this->deleteConfigurations, $this->deleteVolumes, $this->deleteImages, $this->deleteConnectedNetworks); + DeleteService::run($this->resource, $this->deleteConfigurations, $this->deleteVolumes, $this->dockerCleanup, $this->deleteConnectedNetworks); break; } @@ -80,7 +80,7 @@ class DeleteResourceJob implements ShouldBeEncrypted, ShouldQueue || $this->resource instanceof StandaloneDragonfly || $this->resource instanceof StandaloneClickhouse; $server = data_get($this->resource, 'server') ?? data_get($this->resource, 'destination.server'); - if (($this->deleteImages || $isDatabase) && $server) { + if (($this->dockerCleanup || $isDatabase) && $server) { CleanupDocker::run($server, true); } diff --git a/app/Livewire/Project/Shared/Danger.php b/app/Livewire/Project/Shared/Danger.php index 5a49460da..1fe7ec21a 100644 --- a/app/Livewire/Project/Shared/Danger.php +++ b/app/Livewire/Project/Shared/Danger.php @@ -20,7 +20,7 @@ class Danger extends Component public bool $delete_volumes = true; - public bool $delete_images = true; + public bool $docker_cleanup = true; public bool $delete_connected_networks = true; @@ -48,7 +48,7 @@ class Danger extends Component $this->resource, $this->delete_configurations, $this->delete_volumes, - $this->delete_images, + $this->docker_cleanup, $this->delete_connected_networks ); diff --git a/resources/views/components/modal-confirmation.blade.php b/resources/views/components/modal-confirmation.blade.php index 56abba71d..46910310c 100644 --- a/resources/views/components/modal-confirmation.blade.php +++ b/resources/views/components/modal-confirmation.blade.php @@ -8,15 +8,7 @@ 'action' => 'delete', 'content' => null, ]) -
@if ($customButton) @@ -32,7 +24,6 @@ @click="modalOpen=true" class="{{ $buttonFullWidth ? 'w-full' : '' }} {{ $isErrorButton ? 'bg-red-500 hover:bg-red-600 text-white' : '' }}" :disabled="$disabled" - wire:target > {{ $buttonTitle }} @@ -43,7 +34,7 @@ class="fixed top-0 lg:pt-10 left-0 z-[99] flex items-start justify-center w-screen h-screen" x-cloak>

{{ $title }}

+
{{ $slot }} diff --git a/resources/views/livewire/project/shared/danger.blade.php b/resources/views/livewire/project/shared/danger.blade.php index 11521a8c6..d7360310f 100644 --- a/resources/views/livewire/project/shared/danger.blade.php +++ b/resources/views/livewire/project/shared/danger.blade.php @@ -14,23 +14,25 @@ >
-
Select the actions you want to perform:
+
+
Select the actions you want to perform:
+
- +
Cancel - + Continue
@@ -44,6 +46,12 @@
The following actions will be performed:
    +
  • + + + + All containers of this resource will be stopped and permanently deleted. +
  • From 76cb473db80528056a25b22bb10b2ab50385596b Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Sat, 31 Aug 2024 13:06:55 +0200 Subject: [PATCH 108/863] fix default checkbox state --- .../components/modal-confirmation.blade.php | 33 ++++++++++++++----- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/resources/views/components/modal-confirmation.blade.php b/resources/views/components/modal-confirmation.blade.php index acf641203..0896a1bc8 100644 --- a/resources/views/components/modal-confirmation.blade.php +++ b/resources/views/components/modal-confirmation.blade.php @@ -34,7 +34,7 @@ copied: false, submitAction: @js($submitAction), passwordError: '', - selectedActions: [], + selectedActions: @js(collect($checkboxes)->pluck('id')->all()), resetModal() { this.step = this.initialStep; this.deleteText = ''; @@ -73,7 +73,14 @@ this.copied = false; }, 2000); }, - + toggleAction(id) { + const index = this.selectedActions.indexOf(id); + if (index > -1) { + this.selectedActions.splice(index, 1); + } else { + this.selectedActions.push(id); + } + } }" @keydown.escape.window="modalOpen = false; resetModal()" :class="{ 'z-40': modalOpen }" class="relative w-auto h-auto" @password-error.window="passwordError = $event.detail"> @if ($customButton) @if ($buttonFullWidth) @@ -144,7 +151,13 @@
    Select the actions you want to perform:
@foreach($checkboxes as $index => $checkbox) - + @endforeach
@endif @@ -166,12 +179,14 @@ @endforeach @foreach($checkboxes as $checkbox) -
  • - - - - {{ $checkbox['label'] }} -
  • + @endforeach @if($confirmWithText) From bcfca40f3a7c979fed16c26742d797c61553cea6 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Sat, 31 Aug 2024 13:10:45 +0200 Subject: [PATCH 109/863] rest checkboxes on close --- resources/views/components/modal-confirmation.blade.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/resources/views/components/modal-confirmation.blade.php b/resources/views/components/modal-confirmation.blade.php index 0896a1bc8..02283a1a6 100644 --- a/resources/views/components/modal-confirmation.blade.php +++ b/resources/views/components/modal-confirmation.blade.php @@ -41,6 +41,7 @@ this.password = ''; this.userConfirmText = ''; this.passwordError = ''; + this.selectedActions = @js(collect($checkboxes)->pluck('id')->all()); }, step1ButtonText: @js($step1ButtonText), step2ButtonText: @js($step2ButtonText), @@ -157,6 +158,7 @@ :label="$checkbox['label']" x-on:change="toggleAction('{{ $checkbox['id'] }}')" :checked="true" + x-bind:checked="selectedActions.includes('{{ $checkbox['id'] }}')" > @endforeach
    From b118a627d001caef33a1be4bf918b817edb75b4f Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Sat, 31 Aug 2024 13:41:08 +0200 Subject: [PATCH 110/863] fix password validation and password error --- .../components/modal-confirmation.blade.php | 48 +++++++++++-------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/resources/views/components/modal-confirmation.blade.php b/resources/views/components/modal-confirmation.blade.php index 02283a1a6..f8b0c4a26 100644 --- a/resources/views/components/modal-confirmation.blade.php +++ b/resources/views/components/modal-confirmation.blade.php @@ -40,32 +40,34 @@ this.deleteText = ''; this.password = ''; this.userConfirmText = ''; - this.passwordError = ''; this.selectedActions = @js(collect($checkboxes)->pluck('id')->all()); + $wire.$refresh(); }, step1ButtonText: @js($step1ButtonText), step2ButtonText: @js($step2ButtonText), step3ButtonText: @js($step3ButtonText), validatePassword() { - this.passwordError = ''; if (this.confirmWithPassword && !this.password) { - this.passwordError = 'Password is required.'; - return false; + return 'Password is required.'; } - return true; + return ''; }, submitForm() { - if (this.validatePassword()) { - $wire.call(this.submitAction, this.password, this.selectedActions) - .then(result => { - if (result === true) { - this.modalOpen = false; - this.resetModal(); - } else if (typeof result === 'string') { - this.passwordError = result; - } - }); + if (this.confirmWithPassword) { + this.passwordError = this.validatePassword(); + if (this.passwordError) { + return; + } } + $wire.call(this.submitAction, this.password, this.selectedActions) + .then(result => { + if (result === true) { + this.modalOpen = false; + this.resetModal(); + } else if (typeof result === 'string') { + this.passwordError = result; + } + }); }, copyConfirmText() { navigator.clipboard.writeText(this.confirmText); @@ -82,7 +84,7 @@ this.selectedActions.push(id); } } -}" @keydown.escape.window="modalOpen = false; resetModal()" :class="{ 'z-40': modalOpen }" class="relative w-auto h-auto" @password-error.window="passwordError = $event.detail"> +}" @keydown.escape.window="modalOpen = false; resetModal()" :class="{ 'z-40': modalOpen }" class="relative w-auto h-auto"> @if ($customButton) @if ($buttonFullWidth) @@ -134,7 +136,7 @@ @endif -