{"id":32994671,"url":"https://github.com/agencebluedrop/dropfactory-drupal","last_synced_at":"2026-05-16T15:35:11.453Z","repository":{"id":323539236,"uuid":"1091655995","full_name":"Agencebluedrop/DropFactory-Drupal","owner":"Agencebluedrop","description":"Dropfactory is a solution designed to simplify the deployment and management of multiple Drupal websites. It provides a unique and intuitive interface that allows you to manage your entire portfolio of sites without any coding required.","archived":false,"fork":false,"pushed_at":"2025-11-10T17:33:46.000Z","size":582,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-11-10T19:19:55.748Z","etag":null,"topics":["drupal","factory"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Agencebluedrop.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-11-07T10:23:46.000Z","updated_at":"2025-11-10T17:33:49.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/Agencebluedrop/DropFactory-Drupal","commit_stats":null,"previous_names":["agencebluedrop/dropfactory-drupal"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/Agencebluedrop/DropFactory-Drupal","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Agencebluedrop%2FDropFactory-Drupal","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Agencebluedrop%2FDropFactory-Drupal/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Agencebluedrop%2FDropFactory-Drupal/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Agencebluedrop%2FDropFactory-Drupal/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Agencebluedrop","download_url":"https://codeload.github.com/Agencebluedrop/DropFactory-Drupal/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Agencebluedrop%2FDropFactory-Drupal/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":284202058,"owners_count":26964370,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-11-13T02:00:06.582Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["drupal","factory"],"created_at":"2025-11-13T11:00:59.497Z","updated_at":"2026-05-16T15:35:11.440Z","avatar_url":"https://github.com/Agencebluedrop.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# DropFactory\n\nDropfactory is a solution designed to simplify the deployment and management of multiple Drupal websites. It provides a unique and intuitive interface that allows you to manage your entire portfolio of sites without any coding required. This centralized approach enables teams to focus on content creation and user experience, rather than the technical complexities of managing multiple Drupal installations.\n\n**Project Objective**\n\nThe DropFactory project aims to provide Drupal users with an installation and administration console for low-code site factories. Inspired by the Aegir Hosting System, which we previously used, this project seeks to offer a similarly streamlined experience.\nIt was born from the collaboration between a team specializing in the Drupal CMS and a team with expertise in hosting and managing open-source solutions.\n\nDropFactory is presented as a free and open-source solution. As the initiators of its first release, we invite our partners, friends, and Drupal users to get involved in its development and maintenance. We are recruiting both users and testers. Feel free to participate, contact us, or submit issues on this repository.\n\n**Contact Information**\n\nThe DropFactory project is the result of a collaboration between two partners actively involved in open source communities:\n\u003ebluedrop.fr SAS - https://bluedrop.fr\n\u003e\n\u003eEvolix SARL - https://evolix.com\n\n![header dropfactory](https://www.bluedrop.fr/sites/default/files/2025-11/accueil-cartes.svg \"header DropFactory\")\n\n## Install\n\nOn a brand new Debian 12/13 system.\n\nRequirements : \n\n* GNU/Linux Debian 12 (Bookworm) or 13 (Trixie) system dedicated to DropFactory\n* Nginx\n* MariaDB\n* PHP-FPM 8.4 (from deb.sury.org on Debian 12 systems - Debian 13 runs with PHP8.4)\n* NodeJS 22 (from NodeSource repositories)\n* ansible (`apt install ansible`)\n* certbot (`apt install certbot`)\n\n\nSystem settings :\n\n~~~\n## Ensure /home is `exec`\n# vim /etc/fstab\n\n# systemctl daemon-reload\n# mount -o remount /home\n\n## Ensure that created users will have their home directory in 0750\n# echo \"DIR_MODE=0750\" \u003e\u003e /etc/adduser.conf \n~~~\n\nCreate UNIX accounts : \n\n~~~\n# adduser --disabled-password dropfactory\n# adduser --disabled-password --gid $(id --group dropfactory)  www-dropfactory\n\n# adduser www-data dropfactory\n~~~\n\n\u003e *Note*: Here, the complete Dropfactory system is deployed inside one UNIX account (with a separate one for PHP execution).\n\u003e It's also possible to deploy to separate UNIX account the frontend and backend sides. Even on a different server as long as they both \n\u003e Use the same MySQL host\n\n\n\nEnsure the backend will be able to SSH as root localy : \n\n~~~\n# su - dropfactory\n$ ssh-keygen -t ed25519\n$ ^D\n\n# cat ~dropfactory/.ssh/id_ed25519.pub \u003e\u003e .ssh/authorized_keys\n# cat \u003c\u003c UNILIKELY_EOF \u003e\u003e /etc/ssh/sshd_config.d/zzz-evolinux-custom.conf\n\nMatch User root Address 127.0.0.1,::1\n    AllowGroups root\n    PubkeyAuthentication yes\n    PasswordAuthentication no\n    PermitRootLogin without-password\n\nUNILIKELY_EOF\n\n# sshd -t\n# systemctl reload ssh\n\n# su - dropfactory\n$ ssh root@localhost true\n$ if [[ $? -eq 0 ]]; then echo \"SSH OK\"; fi\nSSH OK\n~~~\n\nFetch the code :\n\n~~~\n# su - dropfactory\n$ git clone https://github.com/Agencebluedrop/DropFactory-Drupal.git dropfactory\n~~~\n\nCreate the databases \u0026 their users :\n\n~~~\n# mysqladmin create dropfactory_backend\n# mysqladmin create dropfactory_frontend\n\n# mysql\nMariaDB [(none)]\u003e GRANT ALL PRIVILEGES ON dropfactory_backend.* TO 'dropfactory_backend'@'localhost' IDENTIFIED BY 'PASSWORD';\nMariaDB [(none)]\u003e GRANT ALL PRIVILEGES ON dropfactory_frontend.* TO 'dropfactory_frontend'@'localhost' IDENTIFIED BY 'PASSWORD';\n\nMariaDB [(none)]\u003e GRANT SELECT on dropfactory_backend.* TO 'dropfactory_frontend'@'localhost';\nMariaDB [(none)]\u003e GRANT INSERT on dropfactory_backend.TaskBuffer TO 'dropfactory_frontend'@'localhost';\n~~~\n\n\u003e *Note*: Depending on your MariaDB version, the specific grants for dropfactory_frontend user on the table dropfactory_backend.TaskBuffer\n\u003e may not work before creating the table in the database :'(\n\nConfigure the DropFactory (SQL Credentials, SSH Keys...) :\n\n~~~\n### Frontend : Config, vendor install \u0026 db migration\n# su - dropfactory\n$ cd dropfactory/frontend\n$ cp -a .env .env.local\n$ vim .env.local\n\n$ composer install\n$ php bin/console tailwind:build\n$ php bin/console importmap:install\n$ php bin/console doctrine:migrations:migrate\n\n\n$ ^D\n\n### Backend : Config, ssh key gen\n# su - dropfactory\n$ cd dropfactory/backend\n$ cp -a conf/config.ini.example conf/config.ini\n$ vim conf/config.ini\n\n$ cp -a ansible/vars/main.yml.example ansible/vars/main.yml\n$ vim ansible/vars/main.yml\n\n## This key will be your \"pull/deploy\" for the projects you create (ie: you'll give it read rights on your project repositories)\n$ ssh-keygen -t ed25519 -f conf/deploy_key.ed25519\n~~~\n\n\nNginx vhost :\n\n~~~\n# cat /etc/nginx/sites-available/dropfactory.conf\n\nupstream php_dropfactory {\n        server unix:/home/dropfactory/php-fpm.sock;\n}\n\nserver {\n    listen [::]:80;\n    listen      80;\n    #listen [::]:443 ssl;\n    #listen      443 ssl;\n    #http2 on;\n\n    server_name dropfactory-sandbox.evolix.eu;\n\n    ## SSL\n    #include snippets/letsencrypt.conf;\n    #ssl_certificate /etc/letsencrypt/live/dropfactory/fullchain.pem;\n    #ssl_certificate_key /etc/letsencrypt/live/dropfactory/privkey.pem;\n\n    ## HTTP to HTTP\n    #if ($scheme = http) {\n    #        return 301 https://$host$request_uri;\n    #}\n\n\n    root /home/dropfactory/dropfactory/frontend/public;\n    index index.htm index.html index.php;\n\n    location = /favicon.ico {\n        log_not_found off;\n        access_log off;\n    }\n\n    location = /robots.txt {\n        allow all;\n        log_not_found off;\n        access_log off;\n    }\n\n    # Very rarely should these ever be accessed outside of your lan\n    location ~* \\.(txt|log)$ {\n        deny all;\n    }\n\n    location ~ \\..*/.*\\.php$ {\n        return 403;\n    }\n\n    location ~ ^/sites/.*/private/ {\n        return 403;\n    }\n\n    # Block access to scripts in site files directory\n    location ~ ^/sites/[^/]+/files/.*\\.php$ {\n        deny all;\n    }\n\n    # Allow \"Well-Known URIs\" as per RFC 5785\n    location ~* ^/.well-known/ {\n        allow all;\n    }\n\n    # Block access to \"hidden\" files and directories whose names begin with a\n    # period. This includes directories used by version control systems such\n    # as Subversion or Git to store control files.\n    location ~ (^|/)\\. {\n        return 403;\n    }\n\n    location / {\n        # try_files $uri @rewrite; # For Drupal \u003c= 6\n        try_files $uri /index.php?$query_string; # For Drupal \u003e= 7\n    }\n\n    location @rewrite {\n        rewrite ^/(.*)$ /index.php?q=$1;\n    }\n\n    # Don't allow direct access to PHP files in the vendor directory.\n    location ~ /vendor/.*\\.php$ {\n        deny all;\n        return 404;\n    }\n\n    # In Drupal 8, we must also match new paths where the '.php' appears in\n    # the middle, such as update.php/selection. The r\n    # and only allows this pattern with the update.php front controller.\n    # This allows legacy path aliases in the form of\n    # blog/index.php/legacy-path to continue to route to Drupal nodes. If\n    # you do not have any paths like that, then you might prefer to use a\n    # laxer rule, such as:\n    #   location ~ \\.php(/|$) {\n    # The laxer rule will continue to work if Drupal uses this new URL\n    # pattern with front controllers other than update.php in a future\n    # release.\n    location ~ '\\.php$|^/update.php' {\n        # Ensure the php file exists. Mitigates CVE-2019-11043\n        #try_files $uri =404;\n        fastcgi_split_path_info ^(.+?\\.php)(|/.*)$;\n        fastcgi_buffers 16 16k;\n        fastcgi_buffer_size 32k;\n        # Security note: If you're running a version of PHP older than the\n        # latest 5.3, you should have \"cgi.fix_pathinfo = 0;\" in php.ini.\n        # See http://serverfault.com/q/627903/94922 for details.\n        include snippets/fastcgi-php.conf;\n        # Block httpoxy attacks. See https://httpoxy.org/.\n        fastcgi_param HTTP_PROXY \"\";\n        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;\n        fastcgi_param PATH_INFO $fastcgi_path_info;\n        fastcgi_param QUERY_STRING $query_string;\n        fastcgi_intercept_errors on;\n\n        fastcgi_pass php_dropfactory;\n    }\n\n    # Fighting with Styles? This little gem is amazing.\n    # location ~ ^/sites/.*/files/imagecache/ { # For Drupal \u003c= 6\n    location ~ ^/sites/.*/files/styles/ { # For Drupal \u003e= 7\n        try_files $uri @rewrite;\n    }\n\n    # Handle private files through Drupal. Private file's path can come\n    # with a language prefix.\n    location ~ ^(/[a-z\\-]+)?/system/files/ { # For Drupal \u003e= 7\n        try_files $uri /index.php?$query_string;\n    }\n\n    location ~* \\.(js|css|png|jpg|jpeg|gif|ico|svg)$ {\n        try_files $uri @rewrite;\n        expires max;\n        log_not_found off;\n    }\n    # Enforce clean URLs\n    # Removes index.php from urls like www.example.com/index.php/my-page --\u003e www.example.com/my-page\n    # Could be done with 301 for permanent or other redirect codes.\n    if ($request_uri ~* \"^(.*/)index\\.php(.*)\") {\n        return 307 $1$2;\n    }\n}\n\n# ln -s /etc/nginx/sites-available/dropfactory.conf /etc/nginx/sites-enabled/\n# nginx -t \n# systemctl reload nginx\n~~~\n\nTo enable SSL on the vhost, uncomment the `include snippets/letsencrypt.conf;` directive and add the following file : \n\n~~~\n# cat /etc/nginx/snippets/letsencrypt.conf\nlocation ~ /.well-known/acme-challenge {\n    alias /var/lib/letsencrypt/;\n    try_files $uri =404;\n    auth_basic off;\n    allow all;\n}\n~~~\n\n~~~\n# certbot certonly --webroot --webroot-path /var/lib/letsencrypt/ -d dropfactory-sandbox.evolix.eu --cert-name dropfactory\n~~~\n\nYou can now uncomment the rest of the SSL related directives \u0026 the listen on port 443 (HTTPS)\n\n\nPHP-FPM : \n\n~~~\n# cat \u003c\u003c UNILIKELY_EOF \u003e /etc/php/8.4/fpm/pool.d/dropfactory.conf\n[dropfactory]\nuser = www-dropfactory\ngroup = dropfactory\n\n\nlisten = /home/dropfactory/php-fpm.sock\nlisten.owner = dropfactory\nlisten.group = www-data\n\npm = ondemand\npm.status_path = /fpm-status\npm.max_children = 20\npm.process_idle_timeout = 10s\npm.max_requests = 1000\n\nUNILIKELY_EOF\n\n# php-fpm8.4 -t\n# systemctl reload php8.4-fpm\n~~~\n\nEnable the backend crontab to treat jobs :\n\n~~~\n# touch /var/log/dropfactory_output.log\n# chown dropfactory:adm /var/log/dropfactory_output.log\n\n# cat /etc/logrotate.d/dropfactory\n/var/log/dropfactory_output.log {\n        daily\n        missingok\n        rotate 365\n        compress\n        delaycompress\n        notifempty\n        create 0640 dropfactory adm\n}\n\n\n# su - dropfactory\n\n$ crontab -e\n*/5 *  *   *   *     cd /home/dropfactory/dropfactory/backend/; date \u003e\u003e /var/log/dropfactory_output.log; php cron.php 2\u003e\u00261 \u003e\u003e /var/log/dropfactory_output.log\n~~~","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fagencebluedrop%2Fdropfactory-drupal","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fagencebluedrop%2Fdropfactory-drupal","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fagencebluedrop%2Fdropfactory-drupal/lists"}