├── .beetbox └── config.yml ├── .github ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .gitmodules ├── Dockerfile ├── README.md ├── RoboFile.php ├── Vagrantfile ├── circle.yml ├── composer.json ├── composer.lock ├── composer └── src │ └── Plugin.php ├── dependencies.yml ├── docs ├── configuration │ ├── ansible │ │ ├── config.yml.md │ │ ├── custom-playbook.md │ │ ├── custom-tasks.md │ │ ├── galaxy-roles.md │ │ └── global-config.md │ └── vagrant │ │ └── Vagrantfile.local.md ├── contributing │ └── contributing.md ├── index.md └── packer │ └── builds.md ├── phpunit.xml.dist ├── provisioning ├── ansible │ ├── config │ │ ├── default.config.yml │ │ └── profiles │ │ │ ├── acquia │ │ │ ├── blt.config.yml │ │ │ └── php5.6.config.yml │ │ │ ├── beetbox.config.yml │ │ │ ├── pantheon │ │ │ └── .gitkeep │ │ │ └── platform.sh │ │ │ └── .gitkeep │ ├── playbook-config.yml │ ├── playbook-provision.yml │ ├── playbook-setup.yml │ ├── roles │ │ ├── beetbox-apparmor │ │ │ └── tasks │ │ │ │ └── main.yml │ │ ├── beetbox-apt-repos │ │ │ └── tasks │ │ │ │ └── main.yml │ │ ├── beetbox-docker │ │ │ ├── files │ │ │ │ ├── start.sh │ │ │ │ └── supervisord.conf │ │ │ └── tasks │ │ │ │ └── main.yml │ │ ├── beetbox-init │ │ │ └── tasks │ │ │ │ └── main.yml │ │ ├── beetbox-known-hosts │ │ │ └── tasks │ │ │ │ └── main.yml │ │ ├── beetbox-packages │ │ │ └── tasks │ │ │ │ └── main.yml │ │ ├── beetbox-packer │ │ │ ├── defaults │ │ │ │ └── main.yml │ │ │ └── tasks │ │ │ │ └── main.yml │ │ ├── beetbox-php-nginx │ │ │ ├── defaults │ │ │ │ └── main.yml │ │ │ ├── tasks │ │ │ │ └── main.yml │ │ │ └── templates │ │ │ │ └── nginx-vhost.conf.j2 │ │ ├── beetbox-symlinks │ │ │ └── tasks │ │ │ │ └── main.yml │ │ ├── beetbox-ubuntu │ │ │ ├── files │ │ │ │ └── refresh-apt.conf │ │ │ └── tasks │ │ │ │ └── main.yml │ │ ├── beetbox-vagrant │ │ │ └── tasks │ │ │ │ └── main.yml │ │ ├── beetbox-virtualbox │ │ │ └── tasks │ │ │ │ ├── main.yml │ │ │ │ └── virtualbox.yml │ │ └── beetbox-web │ │ │ └── tasks │ │ │ └── main.yml │ └── templates │ │ ├── motd.sh.j2 │ │ └── welcome.txt.j2 ├── beetbox.sh ├── packer │ ├── http │ │ └── preseed.cfg │ └── scripts │ │ ├── cleanup.sh │ │ └── minimize.sh └── ubuntu-16.04.json └── tests └── PluginTest.php /.beetbox/config.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Vagrant config. 3 | vagrant_ip: 192.168.88.88 4 | vagrant_box: beet/dev 5 | 6 | # Beetbox settings. 7 | beet_project: drupal 8 | beet_domain: "beetbox.local" 9 | beet_root: "{{ beet_base }}/projects/{{ beet_project }}" 10 | beet_mysql_database: "beetbox_{{ beet_project }}" 11 | beet_site_name: "Beetbox" 12 | 13 | # Drupal settings. 14 | drupal_create_makefile: yes 15 | drupal_build_makefile: yes 16 | drupal_install_site: yes 17 | drupal_account_name: admin 18 | drupal_account_pass: admin 19 | drush_create_alias: yes 20 | php_memory_limit: "284M" 21 | 22 | # Beetbox debug. 23 | beet_debug: yes 24 | 25 | # 26 | # Examples. 27 | # 28 | 29 | # Backdrop. 30 | #beet_project: backdrop 31 | #backdrop_checkout: yes 32 | #backdrop_version: "1.2.2" 33 | #backdrop_install_site: yes 34 | #backdrop_account_name: admin 35 | #backdrop_account_pass: admin 36 | 37 | # CakePHP. 38 | #beet_project: cakephp 39 | #cake_create_project: yes 40 | #beet_mysql_database: "my_app" 41 | #beet_mysql_user: "my_app" 42 | #beet_mysql_password: "secret" 43 | 44 | # Drupal composer. 45 | #beet_root: "{{ beet_base }}/projects/{{ beet_project }}-composer" 46 | #beet_web: "{{ beet_root }}/web" 47 | #drupal_build_makefile: no 48 | #drupal_build_composer: yes 49 | #drupal_account_name: admin 50 | #drupal_account_pass: admin 51 | 52 | # Kohana. 53 | #beet_project: kohana 54 | #kohana_checkout: yes 55 | #kohana_version: "v3.3.4" 56 | #kohana_configure: yes 57 | #kohana_remove_install: yes 58 | 59 | # Modx. 60 | #beet_project: modx 61 | #modx_checkout: yes 62 | #modx_version: "2.x" 63 | #modx_install_site: yes 64 | #modx_account_name: admin 65 | #modx_account_pass: admin 66 | 67 | # Silverstripe. 68 | #beet_project: silverstripe 69 | #ss_create_project: yes 70 | #ss_install_site: yes 71 | #ss_account_name: admin 72 | #ss_account_pass: admin 73 | 74 | # Slim. 75 | #beet_project: slim 76 | #slim_create_new: yes 77 | #slim_add_example: yes 78 | #slim_add_htaccess: yes 79 | 80 | # Symfony 81 | #beet_project: symfony 82 | #beet_web: "{{ beet_root }}/{{ symfony_project_name }}/web" 83 | #symfony_project_create: yes 84 | #symfony_project_name: beetbox 85 | 86 | # WordPress. 87 | #beet_project: wordpress 88 | #wp_download_core: yes 89 | #wp_install_site: yes 90 | #wp_account_name: admin 91 | #wp_account_pass: admin 92 | #wp_account_email: "admin@beetbox.local" 93 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contributing Guide 2 | ================== 3 | 4 | Firstly, thanks for taking the time to contribute! 5 | 6 | The following is a set of guidelines for contributing to the project. These are just guidelines, not rules, that are designed to help your contributions here succeed. Please use your best judgment and feel free to propose changes to this document in a pull request. 7 | 8 | If you haven't already, please take the time to read through the complete [Contributing guide][] for the project. It should help ensure your contributions succeed by aligning them with the goals for the project. 9 | 10 | **We want you to contribute the things you're excited about so everyone can benefit.** 11 | 12 | [Contributing guide]: http://beetbox.readthedocs.io/en/stable/contributing/contributing/ 13 | 14 | Proposing Changes 15 | ----------------- 16 | 17 | Please submit a [GitHub Pull Request][] with a clear list of what you've done. 18 | 19 | When you send a pull request with a new or changed feature, we will love you forever if you also include documentation or tests. 20 | 21 | Please ensure all of your commits are atomic (one feature per commit) and have a clear log message (read on below). 22 | 23 | [GitHub Pull Request]: https://github.com/beetboxvm/beetbox/pull/new/master 24 | [pull requests]: http://help.github.com/pull-requests/ 25 | 26 | Commit Messages 27 | --------------- 28 | 29 | Always write a clear log message for your commits. One-line messages are fine for small changes, but bigger changes should include more detail. Please do not use an issue number as your commit message. 30 | 31 | Here is a commit message template, adapted from one written by Tim Pope, that you should use as a guide. 32 | 33 | Short (50 chars or less) summary of changes 34 | 35 | More detailed explanatory text, if necessary. Wrap it to 36 | about 72 characters or so. The blank line separating the 37 | summary from the body is critical; tools like rebase can 38 | get confused if you run the two together. 39 | 40 | Further paragraphs come after blank lines. 41 | 42 | - Bullet points are okay, too 43 | 44 | - Typically a hyphen or asterisk is used for the bullet, 45 | with blank lines in between 46 | 47 | If you read and follow the [Git commit guidelines][], when contributing to almost any project, the chances of your contribution being merged as-is will be greatly improved. 48 | 49 | ### Issues 50 | 51 | Please do not use an issue number as your commit message. 52 | 53 | To reference an issue in a commit message follow the [Github Autolinked references][] format **on its own line** after the short summary line. 54 | 55 | This example commit message links to Github issue 555: 56 | 57 | Short (50 chars or less) summary of changes 58 | 59 | More detailed explanatory text, if necessary. Wrap it to 60 | about 72 characters or so. 61 | 62 | GH-555 63 | 64 | If you follow the above example, the Github issue will be autolinked, providing easy reference when viewing on Github. 65 | 66 | [Git commit guidelines]: https://git-scm.com/book/ch5-2.html#Commit-Guidelines 67 | [Github Autolinked references]: https://help.github.com/articles/autolinked-references-and-urls/#issues-and-pull-requests 68 | 69 | Testing 70 | ------- 71 | 72 | Beetbox uses Circle CI for Continuous Integration. When you create a Github Pull Request, Circle CI will initiate a new build and run the configured tests. The results of those tests are reported back to Github on completion. 73 | 74 | [Read the docs on Continuous Integration][] for more details on the build and test configuration. 75 | 76 | Contributions to the tests are welcomed and strongly encouraged. 77 | 78 | [Read the docs on Continuous Integration]: http://beetbox.readthedocs.io/en/stable/continuous-integration/circle-ci/ 79 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Problem/Motivation 2 | 3 | > (Why the issue was filed) 4 | 5 | ## Expected behaviour 6 | 7 | > (What you expected to happen) 8 | 9 | ## Actual behaviour 10 | 11 | > (What actually happened) 12 | 13 | ## Steps to reproduce 14 | 15 | > (How can someone else make/see it happen) 16 | 17 | ## Proposed changes 18 | 19 | > (If you have a proposed change, workaround or fix, describe the rationale behind it) 20 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Proposed Changes 2 | 3 | - Change 4 | - Update 5 | - Fix 6 | 7 | ## Relates To 8 | 9 | - Issue #0 10 | 11 | ## Notify 12 | 13 | - @octocat 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prevent Vagrant related files. 2 | 3 | .bundle/ 4 | .vagrant/ 5 | projects/ 6 | 7 | # Prevent composer related files. 8 | 9 | vendor/ 10 | 11 | # Prevent Ansible related files. 12 | 13 | installed 14 | results-provision.txt 15 | provisioning/ansible/config/* 16 | !provisioning/ansible/config/default.config.yml 17 | !provisioning/ansible/config/profiles/ 18 | !provisioning/ansible/config/default.config.yml 19 | provisioning/packer/includes/* 20 | !provisioning/packer/includes/Vagrantfile 21 | .beetbox/* 22 | !.beetbox/config.yml 23 | !.beetbox/Vagrantfile 24 | workspace/ 25 | provisioning/packer_cache 26 | 27 | # Prevent miscellaneous/system files. 28 | 29 | .DS_Store 30 | .idea 31 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "provisioning/ansible/roles/alexdesignworks.dcr"] 2 | path = provisioning/ansible/roles/alexdesignworks.dcr 3 | url = https://github.com/alexdesignworks/ansible-role-dcr.git 4 | [submodule "provisioning/ansible/roles/beetboxvm.backdrop"] 5 | path = provisioning/ansible/roles/beetboxvm.backdrop 6 | url = https://github.com/beetboxvm/ansible-role-beetbox-backdrop.git 7 | [submodule "provisioning/ansible/roles/beetboxvm.concrete5"] 8 | path = provisioning/ansible/roles/beetboxvm.concrete5 9 | url = https://github.com/beetboxvm/ansible-role-beetbox-concrete5.git 10 | [submodule "provisioning/ansible/roles/beetboxvm.drupal"] 11 | path = provisioning/ansible/roles/beetboxvm.drupal 12 | url = https://github.com/beetboxvm/ansible-role-beetbox-drupal.git 13 | [submodule "provisioning/ansible/roles/beetboxvm.kohana"] 14 | path = provisioning/ansible/roles/beetboxvm.kohana 15 | url = https://github.com/beetboxvm/ansible-role-beetbox-kohana.git 16 | [submodule "provisioning/ansible/roles/beetboxvm.modx"] 17 | path = provisioning/ansible/roles/beetboxvm.modx 18 | url = https://github.com/beetboxvm/ansible-role-beetbox-modx.git 19 | [submodule "provisioning/ansible/roles/beetboxvm.phantomjs"] 20 | path = provisioning/ansible/roles/beetboxvm.phantomjs 21 | url = https://github.com/beetboxvm/ansible-role-beetbox-phantomjs.git 22 | [submodule "provisioning/ansible/roles/beetboxvm.silverstripe"] 23 | path = provisioning/ansible/roles/beetboxvm.silverstripe 24 | url = https://github.com/beetboxvm/ansible-role-beetbox-silverstripe.git 25 | [submodule "provisioning/ansible/roles/beetboxvm.slim"] 26 | path = provisioning/ansible/roles/beetboxvm.slim 27 | url = https://github.com/beetboxvm/ansible-role-beetbox-slim.git 28 | [submodule "provisioning/ansible/roles/beetboxvm.wordpress"] 29 | path = provisioning/ansible/roles/beetboxvm.wordpress 30 | url = https://github.com/beetboxvm/ansible-role-beetbox-wordpress.git 31 | [submodule "provisioning/ansible/roles/ANXS.postgresql"] 32 | path = provisioning/ansible/roles/ANXS.postgresql 33 | url = https://github.com/ANXS/postgresql 34 | [submodule "provisioning/ansible/roles/franklinkim.newrelic"] 35 | path = provisioning/ansible/roles/franklinkim.newrelic 36 | url = https://github.com/weareinteractive/ansible-newrelic.git 37 | [submodule "provisioning/ansible/roles/geerlingguy.adminer"] 38 | path = provisioning/ansible/roles/geerlingguy.adminer 39 | url = https://github.com/geerlingguy/ansible-role-adminer.git 40 | [submodule "provisioning/ansible/roles/geerlingguy.apache"] 41 | path = provisioning/ansible/roles/geerlingguy.apache 42 | url = https://github.com/geerlingguy/ansible-role-apache.git 43 | [submodule "provisioning/ansible/roles/geerlingguy.apache-php-fpm"] 44 | path = provisioning/ansible/roles/geerlingguy.apache-php-fpm 45 | url = https://github.com/geerlingguy/ansible-role-apache-php-fpm.git 46 | [submodule "provisioning/ansible/roles/geerlingguy.blackfire"] 47 | path = provisioning/ansible/roles/geerlingguy.blackfire 48 | url = https://github.com/geerlingguy/ansible-role-blackfire.git 49 | [submodule "provisioning/ansible/roles/geerlingguy.composer"] 50 | path = provisioning/ansible/roles/geerlingguy.composer 51 | url = https://github.com/geerlingguy/ansible-role-composer.git 52 | [submodule "provisioning/ansible/roles/geerlingguy.daemonize"] 53 | path = provisioning/ansible/roles/geerlingguy.daemonize 54 | url = https://github.com/geerlingguy/ansible-role-daemonize.git 55 | [submodule "provisioning/ansible/roles/geerlingguy.drupal-console"] 56 | path = provisioning/ansible/roles/geerlingguy.drupal-console 57 | url = https://github.com/geerlingguy/ansible-role-drupal-console.git 58 | [submodule "provisioning/ansible/roles/geerlingguy.drush"] 59 | path = provisioning/ansible/roles/geerlingguy.drush 60 | url = https://github.com/geerlingguy/ansible-role-drush.git 61 | [submodule "provisioning/ansible/roles/geerlingguy.elasticsearch"] 62 | path = provisioning/ansible/roles/geerlingguy.elasticsearch 63 | url = https://github.com/geerlingguy/ansible-role-elasticsearch.git 64 | [submodule "provisioning/ansible/roles/geerlingguy.firewall"] 65 | path = provisioning/ansible/roles/geerlingguy.firewall 66 | url = https://github.com/geerlingguy/ansible-role-firewall.git 67 | [submodule "provisioning/ansible/roles/geerlingguy.git"] 68 | path = provisioning/ansible/roles/geerlingguy.git 69 | url = https://github.com/geerlingguy/ansible-role-git.git 70 | [submodule "provisioning/ansible/roles/geerlingguy.java"] 71 | path = provisioning/ansible/roles/geerlingguy.java 72 | url = https://github.com/geerlingguy/ansible-role-java.git 73 | [submodule "provisioning/ansible/roles/geerlingguy.mailhog"] 74 | path = provisioning/ansible/roles/geerlingguy.mailhog 75 | url = https://github.com/geerlingguy/ansible-role-mailhog.git 76 | [submodule "provisioning/ansible/roles/geerlingguy.memcached"] 77 | path = provisioning/ansible/roles/geerlingguy.memcached 78 | url = https://github.com/geerlingguy/ansible-role-memcached.git 79 | [submodule "provisioning/ansible/roles/geerlingguy.mysql"] 80 | path = provisioning/ansible/roles/geerlingguy.mysql 81 | url = https://github.com/geerlingguy/ansible-role-mysql.git 82 | [submodule "provisioning/ansible/roles/geerlingguy.nginx"] 83 | path = provisioning/ansible/roles/geerlingguy.nginx 84 | url = https://github.com/geerlingguy/ansible-role-nginx.git 85 | [submodule "provisioning/ansible/roles/geerlingguy.nodejs"] 86 | path = provisioning/ansible/roles/geerlingguy.nodejs 87 | url = https://github.com/geerlingguy/ansible-role-nodejs.git 88 | [submodule "provisioning/ansible/roles/geerlingguy.php"] 89 | path = provisioning/ansible/roles/geerlingguy.php 90 | url = https://github.com/geerlingguy/ansible-role-php.git 91 | [submodule "provisioning/ansible/roles/geerlingguy.php-memcached"] 92 | path = provisioning/ansible/roles/geerlingguy.php-memcached 93 | url = https://github.com/geerlingguy/ansible-role-php-memcached.git 94 | [submodule "provisioning/ansible/roles/geerlingguy.php-mysql"] 95 | path = provisioning/ansible/roles/geerlingguy.php-mysql 96 | url = https://github.com/geerlingguy/ansible-role-php-mysql.git 97 | [submodule "provisioning/ansible/roles/geerlingguy.php-pecl"] 98 | path = provisioning/ansible/roles/geerlingguy.php-pecl 99 | url = https://github.com/geerlingguy/ansible-role-php-pecl.git 100 | [submodule "provisioning/ansible/roles/geerlingguy.php-redis"] 101 | path = provisioning/ansible/roles/geerlingguy.php-redis 102 | url = https://github.com/geerlingguy/ansible-role-php-redis.git 103 | [submodule "provisioning/ansible/roles/geerlingguy.php-xdebug"] 104 | path = provisioning/ansible/roles/geerlingguy.php-xdebug 105 | url = https://github.com/geerlingguy/ansible-role-php-xdebug.git 106 | [submodule "provisioning/ansible/roles/geerlingguy.php-xhprof"] 107 | path = provisioning/ansible/roles/geerlingguy.php-xhprof 108 | url = https://github.com/geerlingguy/ansible-role-php-xhprof.git 109 | [submodule "provisioning/ansible/roles/geerlingguy.pimpmylog"] 110 | path = provisioning/ansible/roles/geerlingguy.pimpmylog 111 | url = https://github.com/geerlingguy/ansible-role-pimpmylog.git 112 | [submodule "provisioning/ansible/roles/geerlingguy.postfix"] 113 | path = provisioning/ansible/roles/geerlingguy.postfix 114 | url = https://github.com/geerlingguy/ansible-role-postfix.git 115 | [submodule "provisioning/ansible/roles/geerlingguy.redis"] 116 | path = provisioning/ansible/roles/geerlingguy.redis 117 | url = https://github.com/geerlingguy/ansible-role-redis.git 118 | [submodule "provisioning/ansible/roles/geerlingguy.ruby"] 119 | path = provisioning/ansible/roles/geerlingguy.ruby 120 | url = https://github.com/geerlingguy/ansible-role-ruby.git 121 | [submodule "provisioning/ansible/roles/geerlingguy.security"] 122 | path = provisioning/ansible/roles/geerlingguy.security 123 | url = https://github.com/geerlingguy/ansible-role-security.git 124 | [submodule "provisioning/ansible/roles/geerlingguy.solr"] 125 | path = provisioning/ansible/roles/geerlingguy.solr 126 | url = https://github.com/geerlingguy/ansible-role-solr.git 127 | [submodule "provisioning/ansible/roles/geerlingguy.varnish"] 128 | path = provisioning/ansible/roles/geerlingguy.varnish 129 | url = https://github.com/geerlingguy/ansible-role-varnish.git 130 | [submodule "provisioning/ansible/roles/hashbangcode.pantheon-cli"] 131 | path = provisioning/ansible/roles/hashbangcode.pantheon-cli 132 | url = https://github.com/hashbangcode/ansible-role-pantheon-cli.git 133 | [submodule "provisioning/ansible/roles/heskethm.wp-cli"] 134 | path = provisioning/ansible/roles/heskethm.wp-cli 135 | url = https://github.com/heskethm/ansible-role-wp-cli.git 136 | [submodule "provisioning/ansible/roles/pwelch.avahi"] 137 | path = provisioning/ansible/roles/pwelch.avahi 138 | url = https://github.com/pwelch/ansible-avahi.git 139 | [submodule "provisioning/ansible/roles/arknoll.selenium"] 140 | path = provisioning/ansible/roles/arknoll.selenium 141 | url = https://github.com/arknoll/ansible-role-selenium.git 142 | [submodule "provisioning/ansible/roles/rvm_io.rvm1-ruby"] 143 | path = provisioning/ansible/roles/rvm_io.rvm1-ruby 144 | url = https://github.com/rvm/rvm1-ansible.git 145 | [submodule "provisioning/ansible/roles/thebinary.lxd"] 146 | path = provisioning/ansible/roles/thebinary.lxd 147 | url = https://github.com/thebinary/ansible-role-lxd.git 148 | [submodule "provisioning/ansible/roles/thom8.php-upload-progress"] 149 | path = provisioning/ansible/roles/thom8.php-upload-progress 150 | url = https://github.com/thom8/ansible-role-php-upload-progress.git 151 | [submodule "provisioning/ansible/roles/beetboxvm.symfony"] 152 | path = provisioning/ansible/roles/beetboxvm.symfony 153 | url = https://github.com/beetboxvm/ansible-role-beetbox-symfony.git 154 | [submodule "provisioning/ansible/roles/beetboxvm.composer"] 155 | path = provisioning/ansible/roles/beetboxvm.composer 156 | url = https://github.com/beetboxvm/ansible-role-beetbox-composer.git 157 | [submodule "provisioning/ansible/roles/pixelart.platformsh-cli"] 158 | path = provisioning/ansible/roles/pixelart.platformsh-cli 159 | url = https://github.com/pixelart/ansible-role-platformsh-cli 160 | [submodule "provisioning/ansible/roles/geerlingguy.php-versions"] 161 | path = provisioning/ansible/roles/geerlingguy.php-versions 162 | url = https://github.com/geerlingguy/ansible-role-php-versions.git 163 | [submodule "provisioning/ansible/roles/cmprescott.chrome-fork"] 164 | path = provisioning/ansible/roles/cmprescott.chrome-fork 165 | url = https://github.com/thom8/ansible-role-chrome.git 166 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:16.04 2 | 3 | WORKDIR /beetbox 4 | 5 | VOLUME ["/var/beetbox"] 6 | 7 | # Copy source files into the build context. 8 | COPY ./provisioning /beetbox/provisioning 9 | 10 | # Provision Beetbox. 11 | RUN /beetbox/provisioning/beetbox.sh 12 | 13 | # Delete innodb log files. 14 | RUN rm /var/lib/mysql/ib_logfile* 15 | 16 | # Allow reprovision. 17 | RUN rm /beetbox/installed 18 | 19 | EXPOSE 22 80 443 20 | CMD ["/bin/bash", "/start.sh"] 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Beetbox - a pre-provisioned L*MP stack 2 | 3 | A VM for local L*MP development, built with Packer, Vagrant + Ansible 4 | 5 | Beetbox is essentially a pre-provisioned version of [Drupal VM](http://www.drupalvm.com/) mainly to speed up initial virtual machine build time, but also to reduce the size of each VM by leveraging [linked clones](https://www.hashicorp.com/blog/vagrant-1-8.html). 6 | 7 | Whilst it contains a set of default feature configuration, it is extremely extensible and almost anything can be overridden/extended with a simple YAML config file. 8 | 9 | It is designed to have an instance (VM) per project and be integrated into a VCS like git, so that configuration can be easily shared within a team and a setup of a new project should be as simple as `git clone ...; vagrant up`. 10 | 11 | This particular project contains the plumbing to manage the automated build of the pre-provisioned Vagrant base box, so almost all functionality is provided by ansible roles external to this project. 12 | 13 | [![Circle CI](https://circleci.com/gh/beetboxvm/beetbox.svg?style=shield)](https://circleci.com/gh/beetboxvm/beetbox) [![Documentation Status](https://readthedocs.org/projects/beetbox/badge/?version=stable)](http://beetbox.readthedocs.org/en/stable/?badge=stable) 14 | [![Latest Stable Version](https://poser.pugx.org/beet/box/v/stable)](https://packagist.org/packages/beet/box) 15 | [![Total Downloads](https://poser.pugx.org/beet/box/downloads)](https://packagist.org/packages/beet/box) 16 | [![License](https://poser.pugx.org/beet/box/license)](https://packagist.org/packages/beet/box) 17 | [![Docker](https://img.shields.io/docker/build/beet/box.svg)](https://hub.docker.com/r/beet/box/builds/) 18 | 19 | ## What's different about this project? 20 | 21 | * It's a composer plugin which automatically creates a Vagrantfile. 22 | * You only add config to your project and don't need to manage a fork of the whole provisioning system. 23 | * It uses a pre-provisioned base box so it’s much faster to provision. 24 | * Each new version of the box gets published to Atlas only if all roles are provisioned making the box always stable. 25 | * With linked clones each VM is a small clone of a single master. 26 | * You can reuse the same provisioning system for a CI environment. 27 | * Minimal host machine dependencies. 28 | 29 | ## Requirements 30 | 31 | * [Composer](https://getcomposer.org/download/) 32 | * [Vagrant](https://www.vagrantup.com/) >= 1.8 33 | * [Virtualbox](https://www.virtualbox.org/) 34 | * [Vagrant Hostsupdater](https://github.com/cogitatio/vagrant-hostsupdater) 35 | ``` 36 | vagrant plugin install vagrant-hostsupdater 37 | ``` 38 | * [Vagrant Auto-network](https://github.com/oscar-stack/vagrant-auto_network) 39 | ``` 40 | vagrant plugin install vagrant-auto_network 41 | ``` 42 | 43 | ## Quickstart 44 | 45 | ``` 46 | composer require --dev beet/box 47 | vagrant up 48 | ``` 49 | 50 | This will automatically generate a Vagrantfile and the `.beetbox` directory, which will contain a `config.yml` file used to configure overrides. 51 | 52 | You can see some examples in [`config.yml`](https://github.com/beetboxvm/beetbox/blob/master/.beetbox/config.yml) 53 | 54 | ## Updating 55 | 56 | ``` 57 | composer update beet/box 58 | ``` 59 | 60 | Version constraints should automatically keep you to the same minor release. `(0.0.x)` 61 | However, you may need to update your configuation when upgrading minor releases. `(0.x.0)` 62 | See the release notes for more information. 63 | 64 | ## Drupal Quickstart 65 | 66 | To get a simple Drupal 8 site up and running with Beetbox, run the following commands: 67 | 68 | ``` 69 | composer create-project drupal-composer/drupal-project:8.x-dev drupal8 --stability dev --no-interaction 70 | cd drupal8 71 | composer require --dev beet/box 72 | vagrant up 73 | ``` 74 | 75 | After which you can install the site at [http://drupal8.local/install.php](http://drupal8.local/install.php) 76 | 77 | or add the following to `./.beetbox/config.yml` and run `vagrant provision` to automatically install drupal: 78 | 79 | ``` 80 | drupal_install_site: yes 81 | drupal_account_name: admin 82 | drupal_account_pass: admin 83 | ``` 84 | 85 | For PHP 5.6 add `php_version: "5.6"` to `./.beetbox/config.yml`, then run `vagrant provision`. 86 | 87 | ## Project roles. 88 | 89 | These roles are mantained by Beetbox team. 90 | 91 | | Project | Build status | 92 | | --- | --- | 93 | | [Backdrop](https://github.com/beetboxvm/ansible-role-beetbox-backdrop) | [![Circle CI](https://circleci.com/gh/beetboxvm/ansible-role-beetbox-backdrop.svg?style=shield)](https://circleci.com/gh/beetboxvm/ansible-role-beetbox-backdrop) | 94 | | [Drupal](https://github.com/beetboxvm/ansible-role-beetbox-drupal) | [![CircleCI](https://circleci.com/gh/beetboxvm/ansible-role-beetbox-drupal.svg?style=shield)](https://circleci.com/gh/beetboxvm/ansible-role-beetbox-drupal) | 95 | | [Kohana](https://github.com/beetboxvm/ansible-role-beetbox-kohana) | [![CircleCI](https://circleci.com/gh/beetboxvm/ansible-role-beetbox-kohana.svg?style=shield)](https://circleci.com/gh/beetboxvm/ansible-role-beetbox-kohana) | 96 | | [Modx](https://github.com/beetboxvm/ansible-role-beetbox-modx) | [![CircleCI](https://circleci.com/gh/beetboxvm/ansible-role-beetbox-modx.svg?style=shield)](https://circleci.com/gh/beetboxvm/ansible-role-beetbox-modx) | 97 | | [Silverstripe](https://github.com/beetboxvm/ansible-role-beetbox-silverstripe) | [![CircleCI](https://circleci.com/gh/beetboxvm/ansible-role-beetbox-silverstripe.svg?style=shield)](https://circleci.com/gh/beetboxvm/ansible-role-beetbox-silverstripe) | 98 | | [Slim](https://github.com/beetboxvm/ansible-role-beetbox-slim) | [![CircleCI](https://circleci.com/gh/beetboxvm/ansible-role-beetbox-slim.svg?style=shield)](https://circleci.com/gh/beetboxvm/ansible-role-beetbox-slim) | 99 | | [Symfony](https://github.com/beetboxvm/ansible-role-beetbox-symfony) | [![Circle CI](https://circleci.com/gh/beetboxvm/ansible-role-beetbox-symfony.svg?style=shield)](https://circleci.com/gh/beetboxvm/ansible-role-beetbox-symfony) | 100 | | [Wordpress](https://github.com/beetboxvm/ansible-role-beetbox-wordpress) | [![CircleCI](https://circleci.com/gh/beetboxvm/ansible-role-beetbox-wordpress.svg?style=shield)](https://circleci.com/gh/beetboxvm/ansible-role-beetbox-wordpress) | 101 | 102 | ## Documentation 103 | 104 | http://beetbox.readthedocs.io/en/latest/ 105 | 106 | ## Contributing 107 | 108 | http://beetbox.readthedocs.io/en/latest/contributing/contributing/ 109 | 110 | ## Support 111 | 112 | * Feature requests should be created in the [GitHub Beetbox Issue Queue](https://github.com/beetboxvm/beetbox/issues). 113 | * Bugs should be reported in the [GitHub Beetbox Issue Queue](https://github.com/beetboxvm/beetbox/issues). 114 | * Use pull requests (PRs) to [contribute](http://beetbox.readthedocs.io/en/latest/contributing/contributing/) to Beetbox. 115 | 116 | ## Credits 117 | This project would not be possible without [geerlingguy's](https://github.com/geerlingguy) awesome Ansible roles from [Drupal VM](https://github.com/geerlingguy/drupal-vm). 118 | We encourage you to support him by buying his book [Ansible for DevOps](http://ansiblefordevops.com/). 119 | 120 | [JetBrains](https://www.jetbrains.com/phpstorm/) generously offer an Open source licence. 121 | 122 | Beetbox is primarily maintained by the Drupal Melbourne (Australia) community. 123 | 124 | Please follow [@beetboxvm](https://twitter.com/beetboxvm) for announcements. 125 | 126 | ## License 127 | 128 | This project is licensed under the [MIT](https://opensource.org/licenses/MIT) open source license. 129 | -------------------------------------------------------------------------------- /RoboFile.php: -------------------------------------------------------------------------------- 1 | taskDockerRun($image) 21 | ->name($name) 22 | ->exec('/beetbox/provisioning/beetbox.sh') 23 | ->volume(__DIR__ . '/', '/beetbox/') 24 | ->volume(__DIR__, '/var/beetbox') 25 | ->interactive() 26 | ->run(); 27 | 28 | if ($build->wasSuccessful()) { 29 | // Commit build container to an image. 30 | $this->taskDockerCommit($build['cid']) 31 | ->name($name) 32 | ->run(); 33 | 34 | // Remove build container. 35 | $this->taskDockerRemove($name) 36 | ->printed(FALSE) 37 | ->option('force') 38 | ->option('volumes') 39 | ->run(); 40 | } 41 | 42 | return $build; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | require 'fileutils' 5 | require 'json' 6 | require 'yaml' 7 | 8 | Vagrant.require_version '>= 1.8.5' 9 | 10 | beet_root = ENV['BEET_ROOT_DIR'] || "#{__dir__}" 11 | config_dir = ENV['BEET_CONFIG_DIR'] || "#{beet_root}/.beetbox" 12 | project_config = "#{config_dir}/config.yml" 13 | local_config = "#{config_dir}/local.config.yml" 14 | composer_conf = JSON.parse(ENV['COMPOSER'] || File.read("#{beet_root}/composer.json")) 15 | vendor_dir = ENV['COMPOSER_VENDOR_DIR'] || composer_conf.fetch('config', {}).fetch('vendor-dir', 'vendor') 16 | default_config = "#{beet_root}/#{vendor_dir}/beet/box/provisioning/ansible/config/default.config.yml" 17 | default_config = "#{beet_root}/provisioning/ansible/config/default.config.yml" if !File.exist?(default_config) 18 | 19 | # Default vagrant config. 20 | vconfig = YAML::load_file(default_config) 21 | vconfig['beet_domain'] = beet_root.split('/').last.gsub(/[\._]/, '-') + ".local" 22 | 23 | # Create config directory. 24 | FileUtils.mkdir_p config_dir 25 | 26 | # Create config.yml from composer config. 27 | cconfig = composer_conf['extra']['beetbox'] rescue nil 28 | File.open(project_config, "w") { |f| f.write(cconfig.to_yaml) } if cconfig.is_a?(Hash) 29 | 30 | # Create default config file. 31 | default_config = "---\nbeet_domain: #{vconfig['beet_domain']}\n" 32 | File.open(project_config, "w") { |f| f.write(default_config) } if !File.exist?(project_config) 33 | 34 | # Copy config from host. 35 | host_config = "#{Dir.home}/.beetbox/config.yml" 36 | if File.exist?(host_config) 37 | FileUtils.cp(host_config, "#{config_dir}/host.config.yml") 38 | end 39 | 40 | pconfig = YAML::load_file(project_config) || nil 41 | vconfig = vconfig.merge pconfig if !pconfig.nil? 42 | 43 | # Merge local.config.yml 44 | if File.exist?(local_config) 45 | lconfig = YAML::load_file(local_config) || nil 46 | vconfig = vconfig.merge lconfig if !lconfig.nil? 47 | end 48 | 49 | # Replace variables in YAML config. 50 | vconfig.each do |key, value| 51 | while vconfig[key].is_a?(String) && vconfig[key].match(/{{ .* }}/) 52 | vconfig[key] = vconfig[key].gsub(/{{ (.*?) }}/) { |match| match = vconfig[$1] } 53 | end 54 | end 55 | 56 | hostname = vconfig['beet_domain'] 57 | branches = ['beetbox'] 58 | current_branch = 'beetbox' 59 | 60 | Vagrant.configure("2") do |config| 61 | 62 | # Hosts file plugins. 63 | if Vagrant.has_plugin?('vagrant-hostsupdater') 64 | config.hostsupdater.aliases = vconfig['beet_aliases'] 65 | elsif Vagrant.has_plugin?('vagrant-hostmanager') 66 | config.hostmanager.enabled = true 67 | config.hostmanager.manage_host = true 68 | config.hostmanager.aliases = vconfig['beet_aliases'] 69 | end 70 | 71 | # Multidev config. 72 | if vconfig['beet_mode'] == 'multidev' 73 | branches = %x(git branch | tr -d '* ').split(/\n/).reject(&:empty?) 74 | branches.unshift("beetbox") 75 | current_branch = %x(git branch | grep '*' | tr -d '* \n') 76 | vconfig['vagrant_ip'] = "0.0.0.0" 77 | branch_prefix = true 78 | end 79 | 80 | # Check for plugins and attempt to install if not (Windows only). 81 | if Vagrant::Util::Platform.windows? 82 | %x(vagrant plugin install vagrant-hostsupdater) unless Vagrant.has_plugin?('vagrant-hostsupdater') 83 | raise 'Your config requires hostsupdater plugin.' unless Vagrant.has_plugin?('vagrant-hostsupdater') 84 | if vconfig['vagrant_ip'] == "0.0.0.0" 85 | %x(vagrant plugin install vagrant-auto_network) unless Vagrant.has_plugin?('vagrant-auto_network') 86 | raise 'Your config requires auto_network plugin.' unless Vagrant.has_plugin?('vagrant-auto_network') 87 | end 88 | end 89 | 90 | # Vagrant Cachier config. 91 | if Vagrant.has_plugin?("vagrant-cachier") 92 | # Configure cached packages to be shared between instances of the same base box. 93 | # More info on http://fgrehm.viewdocs.io/vagrant-cachier/usage 94 | config.cache.scope = :box 95 | config.cache.enable :generic, { "drush" => { cache_dir: "/home/vagrant/.drush/cache" }, } 96 | config.cache.synced_folder_opts = { 97 | type: :nfs, 98 | mount_options: ['rw', 'vers=3', 'tcp', 'nolock'] 99 | } 100 | end 101 | 102 | if Vagrant.has_plugin?('vagrant-exec') 103 | config.exec.commands "*", directory: "#{vconfig['beet_base']}" 104 | end 105 | 106 | branches.each do |branch| 107 | active_node = (branch == current_branch) ? true : false 108 | config.vm.define branch, autostart: active_node, primary: active_node do |node| 109 | 110 | node.vm.box = vconfig['vagrant_box'] 111 | node.vm.box_version = vconfig['vagrant_box_version'] 112 | node.vm.hostname = (branch_prefix) ? "#{branch}.#{hostname}" : hostname 113 | node.ssh.insert_key = false 114 | node.ssh.forward_agent = true 115 | 116 | # Network config. 117 | if vconfig['vagrant_ip'] == "0.0.0.0" && Vagrant.has_plugin?('vagrant-auto_network') 118 | node.vm.network :private_network, :ip => "0.0.0.0", :auto_network => true 119 | elsif vconfig['vagrant_ip'] == "0.0.0.0" 120 | node.vm.network :private_network, :type => "dhcp" 121 | else 122 | node.vm.network :private_network, ip: vconfig['vagrant_ip'] 123 | end 124 | 125 | # Synced folders. 126 | node.vm.synced_folder ".", vconfig['beet_base'], 127 | type: "nfs", 128 | id: "beetbox" 129 | 130 | if vconfig['beet_debug'] 131 | node.vm.synced_folder "./provisioning", "#{vconfig['beet_home']}/provisioning", 132 | type: "nfs", 133 | id: "debug" 134 | debug_mode = "BEET_DEBUG=true" 135 | end 136 | 137 | if vconfig['beet_provision'] 138 | # Provision box 139 | beet_sh = "#{vconfig['beet_home']}/provisioning/beetbox.sh" 140 | beet_profile = ENV['BEET_PROFILE'] || "#{vconfig['beet_profile']}" 141 | beet_sh_playbook = ENV['BEET_PLAY'] || "#{vconfig['beet_provision_playbook']}" 142 | beet_sh_tags = ENV['BEET_TAGS'] || "#{vconfig['beet_provision_tags']}" 143 | local_provision = "sudo chmod +x #{beet_sh} && #{debug_mode} BEET_PROFILE=#{beet_profile} BEET_PLAYBOOK=#{beet_sh_playbook} BEET_TAGS=#{beet_sh_tags} #{beet_sh}" 144 | remote_provision = "sudo apt-get -y install curl && curl -fsSL http://bit.ly/beetbuild | bash -Ee" 145 | node.vm.provision "ansible", type: "shell" do |s| 146 | s.privileged = false 147 | s.inline = "if [ -f #{beet_sh} ]; then #{local_provision}; else #{remote_provision}; fi" 148 | end 149 | end 150 | 151 | # VirtualBox. 152 | node.vm.provider :virtualbox do |v| 153 | v.name = "#{node.vm.hostname}.#{Time.now.to_i}" 154 | v.memory = vconfig['vagrant_memory'] 155 | v.cpus = vconfig['vagrant_cpus'] 156 | v.linked_clone = true 157 | v.customize ["modifyvm", :id, 158 | "--natdnshostresolver1", "on", 159 | "--ioapic", "on", 160 | "--vrde", "off" 161 | ] 162 | end 163 | 164 | # VMware Fusion. 165 | config.vm.provider :vmware_fusion do |v, override| 166 | override.vm.box = "ubuntu/trusty64" 167 | v.gui = false 168 | v.vmx['memsize'] = vconfig['vagrant_memory'] 169 | v.vmx['numvcpus'] = vconfig['vagrant_cpus'] 170 | end 171 | 172 | # Parallels. 173 | config.vm.provider :parallels do |p, override| 174 | override.vm.box = "parallels/ubuntu-14.04" 175 | p.name = "#{node.vm.hostname}.#{Time.now.to_i}" 176 | p.memory = vconfig['vagrant_memory'] 177 | p.cpus = vconfig['vagrant_cpus'] 178 | p.update_guest_tools = true 179 | end 180 | 181 | end 182 | end 183 | end 184 | 185 | # Create local drush alias. 186 | if vconfig['drush_create_alias'] && vconfig['beet_project'] == 'drupal' && File.directory?("#{Dir.home}/.drush") 187 | 188 | alias_file = vconfig['drush_alias_file'] || "#{Dir.home}/.drush/"+hostname+".aliases.drushrc.php" 189 | alias_file = "#{project_root}/#{vconfig['drush_alias_file']}" if vconfig['drush_alias_file'] 190 | 191 | if ARGV[0] == "destroy" 192 | File.delete(alias_file) if File.exist?(alias_file) 193 | else 194 | require 'erb' 195 | class DrushAlias 196 | attr_accessor :hostname, :uri, :key, :root 197 | def template_binding 198 | binding 199 | end 200 | end 201 | 202 | template = <'] = array( 206 | 'uri' => '<%= @uri %>', 207 | 'remote-host' => '<%= @uri %>', 208 | 'remote-user' => 'vagrant', 209 | 'ssh-options' => '-i <%= @key %> -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no', 210 | 'root' => '<%= @root %>', 211 | ); 212 | ALIAS 213 | 214 | alias_file = File.open(alias_file, "w+") 215 | da = DrushAlias.new 216 | da.hostname = vconfig['drush_alias_name'] || hostname 217 | da.uri = hostname 218 | da.key = "#{Dir.home}/.vagrant.d/insecure_private_key" 219 | da.root = vconfig['beet_web'] ||= vconfig['beet_root'] ||= vconfig['beet_base'] 220 | alias_file << ERB.new(template).result(da.template_binding) 221 | alias_file.close 222 | end 223 | end 224 | 225 | # Load local Vagrantfile, if exists. 226 | include_vagrantfile_root = "#{beet_root}/Vagrantfile.local" 227 | load include_vagrantfile_root if File.exist?(include_vagrantfile_root) 228 | include_vagrantfile_conf = "#{config_dir}/Vagrantfile.local" 229 | load include_vagrantfile_conf if File.exist?(include_vagrantfile_conf) 230 | -------------------------------------------------------------------------------- /circle.yml: -------------------------------------------------------------------------------- 1 | --- 2 | machine: 3 | php: 4 | version: 7.1.9 # https://circleci.com/docs/1.0/build-image-trusty/#php 5 | services: 6 | - docker 7 | checkout: 8 | post: 9 | - git submodule sync 10 | - git submodule update --init 11 | dependencies: 12 | cache_directories: 13 | - ~/.composer/cache 14 | override: 15 | - sudo apt-add-repository "deb http://archive.ubuntu.com/ubuntu trusty-backports main restricted universe" 16 | - sudo apt-get update -qq 17 | - sudo apt-get install shellcheck 18 | - composer validate 19 | - composer install 20 | test: 21 | override: 22 | - shellcheck provisioning/beetbox.sh 23 | - composer security 24 | - phpunit 25 | - vendor/bin/robo provision ubuntu:16.04 beet_test 26 | deployment: 27 | dev: 28 | branch: master 29 | owner: beetboxvm 30 | commands: 31 | - > 32 | docker run -i -v $(pwd):/beetbox -i beet_test 33 | packer push 34 | -token=$ATLAS_TOKEN 35 | -name="beet/dev" 36 | -var "cloud_token=$VAGRANT_CLOUD_TOKEN" 37 | -var "beet_repo=$CIRCLE_REPOSITORY_URL.git" 38 | -var "box_version=0.8.$CIRCLE_BUILD_NUM" 39 | /beetbox/provisioning/ubuntu-16.04.json 40 | release: 41 | tag: /[0-9]+\.[0-9]+\.[0-9]+/ 42 | owner: beetboxvm 43 | commands: 44 | - > 45 | docker run -i -v $(pwd):/beetbox -i beet_test 46 | packer push 47 | -token=$ATLAS_TOKEN 48 | -name="beet/box" 49 | -var "cloud_build_name=box" 50 | -var "cloud_token=$VAGRANT_CLOUD_TOKEN" 51 | -var "beet_repo=$CIRCLE_REPOSITORY_URL.git" 52 | -var "beet_version=$CIRCLE_TAG" 53 | -var "box_version=$CIRCLE_TAG" 54 | /beetbox/provisioning/ubuntu-16.04.json 55 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "beet/box", 3 | "description": "A pre-provisioned L*MP stack VM", 4 | "homepage": "https://github.com/beetboxvm/beetbox", 5 | "type": "composer-plugin", 6 | "license": "MIT", 7 | "support": { 8 | "issues": "https://github.com/beetboxvm/beetbox/issues", 9 | "source": "https://github.com/beetboxvm/beetbox", 10 | "docs": "http://beetbox.readthedocs.io/en/latest" 11 | }, 12 | "config": { 13 | "process-timeout": 1200, 14 | "sort-packages": true 15 | }, 16 | "require": { 17 | "composer-plugin-api": "^1.0" 18 | }, 19 | "require-dev": { 20 | "composer/composer": "1.6.5", 21 | "consolidation/robo": "1.2.3", 22 | "phpunit/phpunit": "6.5.8", 23 | "sensiolabs/security-checker": "^4.0" 24 | }, 25 | "autoload": { 26 | "psr-4": { 27 | "Beet\\Box\\": "composer/src/" 28 | } 29 | }, 30 | "scripts": { 31 | "test": [ 32 | "@composer validate", 33 | "@security", 34 | "phpunit --colors=always", 35 | "robo provision ubuntu:16.04 beet_test --ansi" 36 | ], 37 | "security": "security-checker security:check", 38 | "role-update": "git submodule foreach git pull origin master" 39 | }, 40 | "extra": { 41 | "class": "Beet\\Box\\Plugin", 42 | "branch-alias": { 43 | "dev-master": "1.0.x-dev" 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /composer/src/Plugin.php: -------------------------------------------------------------------------------- 1 | composer = $composer; 34 | $this->io = $io; 35 | } 36 | 37 | /** 38 | * {@inheritdoc} 39 | */ 40 | public static function getSubscribedEvents() { 41 | return array( 42 | ScriptEvents::POST_INSTALL_CMD => 'addVagrantfile', 43 | ScriptEvents::POST_UPDATE_CMD => 'addVagrantfile', 44 | ); 45 | } 46 | 47 | /** 48 | * Add/update project Vagrantfile. 49 | * 50 | * @param \Composer\Script\Event $event 51 | */ 52 | public function addVagrantfile(Event $event) { 53 | 54 | $baseDir = dirname(Factory::getComposerFile()); 55 | $source = __DIR__ . '/../../Vagrantfile'; 56 | $target = $baseDir . '/Vagrantfile'; 57 | 58 | if (file_exists($source)) { 59 | if (!file_exists($target) || md5_file($source) != md5_file($target)) { 60 | copy($source, $target); 61 | } 62 | } 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /dependencies.yml: -------------------------------------------------------------------------------- 1 | collectors: 2 | 3 | - type: php-composer 4 | path: / 5 | actors: 6 | # pull requests for updates to our major version 7 | - type: php-composer 8 | versions: "L.Y.Y" 9 | # create issues for new major versions 10 | - type: repo-issue 11 | versions: "Y.0.0" 12 | -------------------------------------------------------------------------------- /docs/configuration/ansible/config.yml.md: -------------------------------------------------------------------------------- 1 | # config.yml 2 | 3 | This is the main method to customise the VM. 4 | 5 | In this file you can override any ansible variables provided by beetbox or by the galaxy roles. 6 | 7 | See the [beetbox.config.yml](https://github.com/beetboxvm/beetbox/blob/master/provisioning/ansible/config/default.config.yml) for a full list of variables. 8 | And each role can include their own specific variables, see [the list of roles](https://github.com/beetboxvm/beetbox/blob/master/docs/configuration/ansible/galaxy-roles.md) for more info. 9 | 10 | 11 | # Common overrides 12 | 13 | `vagrant_ip` (string) 14 | 15 | The IP of the VM, by default this is `0.0.0.0` and the `auto-network` plugin will auto assign an IP. 16 | 17 | `vagrant_memory` (string) 18 | 19 | The memory given to the VM. 20 | 21 | `beet_project` (string) 22 | 23 | The beetbox project role to invoke, by default this is `drupal` but you can also set this to `custom` to skip any project specific role. 24 | 25 | `beet_domain` (string) 26 | 27 | The main domain name of the VM, it's also reused as a base for many other variables like the VM name etc. 28 | 29 | `beet_aliases` (list) 30 | 31 | Addtional domains for the VM. 32 | 33 | `beet_base` (string) 34 | 35 | The location which the root of the project is mounted to inside the VM, we don't recommend changing this location as it also requires setting an environment variable `BEET_BASE` so the config directory can be found. 36 | 37 | `beet_root` (string) 38 | 39 | The root of the project, in some cases this might not be the same as the root of the repo. 40 | If your docroot was at `/docroot` inside the repo you would add `beet_root: "{{ beet_base }}/docroot"` 41 | 42 | `beet_web` (string) 43 | 44 | In some cases the web root is not the same as the project root or the root of the repo so you can override this to be the default docroot for Apache. 45 | 46 | # local.config.yml 47 | 48 | This file will override `config.yml` and is usually excluded from the VCS so you can test or add specific override to the local instance. 49 | 50 | This could include increasing the memory for the VM on a machine with lots of memory available. 51 | -------------------------------------------------------------------------------- /docs/configuration/ansible/custom-playbook.md: -------------------------------------------------------------------------------- 1 | # Custom playbook. 2 | 3 | With a custom playbook you're able to specifically define the roles / tasks for your project. 4 | 5 | You first need to set `beet_provision_playbook` to the name of your custom playbook. 6 | 7 | eg. setting `beet_provision_playbook: build` means you would have a playbook named `playbook-build.yml` in `/.beetbox/playbooks`. 8 | 9 | Any playbooks in `/.beetbox/playbooks` are autoloaded during provisioning so you can have multiple then call them by setting a environment variable. 10 | 11 | eg. `BEET_PLAY=custom vagrant provision` would run the playbook @ `/.beetbox/playbooks/playbook-custom.yml` 12 | 13 | ## Notes 14 | 15 | We would recommend starting with our default [provisioning playbook](https://raw.githubusercontent.com/beetboxvm/beetbox/master/provisioning/ansible/playbook-provision.yml) and customising it. 16 | 17 | You can find more info on playbooks here -- http://docs.ansible.com/ansible/playbooks.html 18 | -------------------------------------------------------------------------------- /docs/configuration/ansible/custom-tasks.md: -------------------------------------------------------------------------------- 1 | # Custom tasks. 2 | 3 | Custom tasks are an easy way to extend beetbox by adding your own ansible tasks - http://docs.ansible.com/ansible/playbooks_intro.html#tasks-list 4 | 5 | Tasks are automatically included in the beetbox play before (pre) and after (post) the main provisioning tasks. 6 | 7 | ## pre tasks 8 | 9 | `/.beetbox/tasks/pre/...` 10 | 11 | Include task files in this directory to run before provisioning, for example if you want to install all project composer dependencies you could add the following 12 | 13 | ``` 14 | --- 15 | - name: Install project dependencies with composer. 16 | composer: 17 | command: install 18 | working_dir: "{{ beet_base }}" 19 | become: no 20 | 21 | ``` 22 | 23 | to a file `/.beetbox/tasks/pre/composer.yml`. 24 | 25 | Tasks are run in alphabetical order if you have tasks dependencies and have access to all ansible variables within the scope of the project. 26 | 27 | ## post tasks 28 | 29 | `/.beetbox/tasks/post/...` 30 | 31 | Similar to pre tasks however these are run after the main playbook tasks. 32 | 33 | ## Notes 34 | 35 | Please try to make these tasks idempotent so it doesn't delay provisioning when rerun. 36 | -------------------------------------------------------------------------------- /docs/configuration/ansible/galaxy-roles.md: -------------------------------------------------------------------------------- 1 | 2 | - name: beetboxvm.backdrop 3 | repo: https://github.com/beetboxvm/ansible-role-beetbox-backdrop.git 4 | - name: beetboxvm.cakephp 5 | repo: https://github.com/beetboxvm/ansible-role-beetbox-cakephp.git 6 | - name: beetboxvm.concrete5 7 | repo: https://github.com/beetboxvm/ansible-role-beetbox-concrete5.git 8 | - name: beetboxvm.drupal 9 | repo: https://github.com/beetboxvm/ansible-role-beetbox-drupal.git 10 | - name: beetboxvm.known-hosts 11 | repo: https://github.com/beetboxvm/ansible-role-beetbox-known-hosts.git 12 | - name: beetboxvm.kohana 13 | repo: https://github.com/beetboxvm/ansible-role-beetbox-kohana.git 14 | - name: beetboxvm.modx 15 | repo: https://github.com/beetboxvm/ansible-role-beetbox-modx.git 16 | - name: beetboxvm.packages 17 | repo: https://github.com/beetboxvm/ansible-role-beetbox-packages.git 18 | - name: beetboxvm.phantomjs 19 | repo: https://github.com/beetboxvm/ansible-role-beetbox-phantomjs.git 20 | - name: beetboxvm.silverstripe 21 | repo: https://github.com/beetboxvm/ansible-role-beetbox-silverstripe.git 22 | - name: beetboxvm.slim 23 | repo: https://github.com/beetboxvm/ansible-role-beetbox-slim.git 24 | - name: beetboxvm.symlinks 25 | repo: https://github.com/beetboxvm/ansible-role-beetbox-symlinks.git 26 | - name: beetboxvm.upload-progress 27 | repo: https://github.com/beetboxvm/ansible-role-beetbox-upload-progress.git 28 | - name: beetboxvm.wordpress 29 | repo: https://github.com/beetboxvm/ansible-role-beetbox-wordpress.git 30 | - name: angstwad.docker_ubuntu 31 | repo: https://github.com/angstwad/docker.ubuntu.git 32 | - name: ANXS.postgresql 33 | repo: https://github.com/ANXS/postgresql 34 | - name: franklinkim.newrelic 35 | repo: https://github.com/weareinteractive/ansible-newrelic.git 36 | - name: geerlingguy.adminer 37 | repo: https://github.com/geerlingguy/ansible-role-adminer.git 38 | - name: geerlingguy.apache 39 | repo: https://github.com/geerlingguy/ansible-role-apache.git 40 | - name: geerlingguy.apache-php-fpm 41 | repo: https://github.com/geerlingguy/ansible-role-apache-php-fpm.git 42 | - name: geerlingguy.blackfire 43 | repo: https://github.com/geerlingguy/ansible-role-blackfire.git 44 | - name: geerlingguy.composer 45 | repo: https://github.com/geerlingguy/ansible-role-composer.git 46 | - name: geerlingguy.daemonize 47 | repo: https://github.com/geerlingguy/ansible-role-daemonize.git 48 | - name: geerlingguy.drupal-console 49 | repo: https://github.com/geerlingguy/ansible-role-drupal-console.git 50 | - name: geerlingguy.drush 51 | repo: https://github.com/geerlingguy/ansible-role-drush.git 52 | - name: geerlingguy.firewall 53 | repo: https://github.com/geerlingguy/ansible-role-firewall.git 54 | - name: geerlingguy.git 55 | repo: https://github.com/geerlingguy/ansible-role-git.git 56 | - name: geerlingguy.java 57 | repo: https://github.com/geerlingguy/ansible-role-java.git 58 | - name: geerlingguy.mailhog 59 | repo: https://github.com/geerlingguy/ansible-role-mailhog.git 60 | - name: geerlingguy.memcached 61 | repo: https://github.com/geerlingguy/ansible-role-memcached.git 62 | - name: geerlingguy.mysql 63 | repo: https://github.com/geerlingguy/ansible-role-mysql.git 64 | - name: geerlingguy.nginx 65 | repo: https://github.com/geerlingguy/ansible-role-nginx.git 66 | - name: geerlingguy.nodejs 67 | repo: https://github.com/geerlingguy/ansible-role-nodejs.git 68 | - name: geerlingguy.php 69 | repo: https://github.com/geerlingguy/ansible-role-php.git 70 | - name: geerlingguy.php-memcached 71 | repo: https://github.com/geerlingguy/ansible-role-php-memcached.git 72 | - name: geerlingguy.php-mysql 73 | repo: https://github.com/geerlingguy/ansible-role-php-mysql.git 74 | - name: geerlingguy.php-pecl 75 | repo: https://github.com/geerlingguy/ansible-role-php-pecl.git 76 | - name: geerlingguy.php-redis 77 | repo: https://github.com/geerlingguy/ansible-role-php-redis.git 78 | - name: geerlingguy.php-xdebug 79 | repo: https://github.com/geerlingguy/ansible-role-php-xdebug.git 80 | - name: geerlingguy.php-xhprof 81 | repo: https://github.com/geerlingguy/ansible-role-php-xhprof.git 82 | - name: geerlingguy.pimpmylog 83 | repo: https://github.com/geerlingguy/ansible-role-pimpmylog.git 84 | - name: geerlingguy.postfix 85 | repo: https://github.com/geerlingguy/ansible-role-postfix.git 86 | - name: geerlingguy.redis 87 | repo: https://github.com/geerlingguy/ansible-role-redis.git 88 | - name: geerlingguy.ruby 89 | repo: https://github.com/geerlingguy/ansible-role-ruby.git 90 | - name: geerlingguy.security 91 | repo: https://github.com/geerlingguy/ansible-role-security.git 92 | - name: geerlingguy.solr 93 | repo: https://github.com/geerlingguy/ansible-role-solr.git 94 | - name: geerlingguy.varnish 95 | repo: https://github.com/geerlingguy/ansible-role-varnish.git 96 | - name: hashbangcode.pantheon-cli 97 | repo: https://github.com/hashbangcode/ansible-role-pantheon-cli.git 98 | - name: heskethm.wp-cli 99 | repo: https://github.com/heskethm/ansible-role-wp-cli.git 100 | - name: pwelch.avahi 101 | repo: https://github.com/pwelch/ansible-avahi.git 102 | - name: arknoll.selenium 103 | repo: https://github.com/arknoll/ansible-role-selenium.git 104 | - name: rvm_io.rvm1-ruby 105 | repo: https://github.com/rvm/rvm1-ansible.git 106 | - name: thebinary.lxd 107 | repo: https://github.com/thebinary/ansible-role-lxd.git 108 | - name: alexdesignworks.dcr 109 | repo: https://github.com/alexdesignworks/ansible-role-dcr.git 110 | -------------------------------------------------------------------------------- /docs/configuration/ansible/global-config.md: -------------------------------------------------------------------------------- 1 | # Global config.yml 2 | 3 | Create `~/.beetbox/config.yml` and add any variables you want to apply to all beetbox projects on your host machine. 4 | 5 | Any variables defined here will be overridden by `config.yml` & `local.config.yml` inside the project. 6 | 7 | This file is copied into the project as `host.config.yml` so you can see the global variables in the context of the project variable. 8 | -------------------------------------------------------------------------------- /docs/configuration/vagrant/Vagrantfile.local.md: -------------------------------------------------------------------------------- 1 | # Vagrantfile.local 2 | 3 | The `Vagrantfile.local` can be used to override any default Vagrantfile configuration. 4 | 5 | This can be stored in the root of the project or inside the `/.beetbox` directory. 6 | 7 | The example below mounts the `.beetbox` directory to the home directory of the VM. 8 | 9 | ``` 10 | Vagrant.configure("2") do |config| 11 | 12 | config.vm.define "beetbox" do |beetbox| 13 | 14 | beetbox.vm.synced_folder "/.beetbox", "/home/vagrant/.beetbox", 15 | type: "nfs", 16 | id: "conf" 17 | 18 | end 19 | 20 | end 21 | ``` 22 | 23 | This adds a new mounted directory but you could also override the default mount location or configuration. 24 | 25 | ``` 26 | Vagrant.configure("2") do |config| 27 | 28 | config.vm.define "beetbox" do |beetbox| 29 | 30 | beetbox.vm.synced_folder ".", "/var/beetbox", 31 | type: "rsync", 32 | id: "beetbox" 33 | 34 | end 35 | 36 | end 37 | ``` 38 | -------------------------------------------------------------------------------- /docs/contributing/contributing.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Contributing is easy, the hardest part is knowing which project to add your pull request to. 4 | 5 | The main knowledge required is [Ansible](https://www.ansible.com/): it's pretty easy to pick up and there is very good [Ansible documentation](http://docs.ansible.com/) available. 6 | 7 | The [Beetbox project](https://github.com/beetboxvm/beetbox) is essentially some plumbing to initiate a set of external roles hosted on [Ansible galaxy](https://galaxy.ansible.com). 8 | 9 | We have a few internal Ansible tasks, but these are only for low level setup and a few features like custom tasks and the welcome message you see at the end of provisioning. 10 | 11 | # Setup 12 | 13 | The first step to contributing is to bring up the example project: 14 | 15 | ``` 16 | git clone --recusive https://github.com/beetboxvm/beetbox && cd $_ 17 | vagrant up 18 | ``` 19 | 20 | This has been modified to use a debug mode which will: 21 | 22 | - show more details when provisioning 23 | - mount [`provisioning`](https://github.com/beetboxvm/beetbox/tree/master/provisioning) directory into the VM, so it's editable and changes could be picked up by `vagrant provision` 24 | - checkout the Ansible roles from their source repo, rather than from Ansible galaxy 25 | 26 | From this point you can modify anything inside the [`provisioning`](https://github.com/beetboxvm/beetbox/tree/master/provisioning) directory and apply changes with `vagrant provision`. 27 | 28 | **Note:** sometimes it's easier to disable (comment out) all roles when debugging, but be careful as there can be role dependencies. 29 | 30 | # Forking the project 31 | 32 | Please follow these instructions to [Fork a project on Github](https://help.github.com/articles/fork-a-repo/). 33 | 34 | Next, you'll want to change your local repository to point at your new remote fork and add an upstream remote to keep it up-to-date. 35 | ```sh 36 | git remote set-url origin https://github.com/YOUR_USERNAME/beetbox.git 37 | git remote add upstream https://github.com/beetboxvm/beetbox.git 38 | git fetch --all 39 | ``` 40 | 41 | Please follow these instructions to [Sync a fork and keep it up-to-date](https://help.github.com/articles/syncing-a-fork/). 42 | 43 | Now you should be able to branch and push changes to your fork of the project. 44 | 45 | # Creating a PR 46 | 47 | We use pull requests to accept changes to the project. Please read this article about [using pull requests on Github](https://help.github.com/articles/using-pull-requests/). 48 | 49 | # Roles 50 | 51 | If you find that the task/role you're updating isn't in the Beetbox core, this is because it is an external role. 52 | You can still contribute to these, however they are separate projects. 53 | 54 | The roles we implement are listed in [`/provisioning/ansible/config/beetbox.config.yml`](https://github.com/beetboxvm/beetbox/blob/master/provisioning/ansible/config/beetbox.config.yml#L33). 55 | 56 | The same applies to forking and creating PR's for these roles too, however you'll want to point the role repo to your fork rather than the Beetbox project. 57 | 58 | ``` 59 | cd /path/to/role 60 | git remote set-url origin [git URL of fork] 61 | ``` 62 | 63 | You can now commit and push changes to your fork for creating a PR on the external project. 64 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # Beetbox - a pre-provisioned L*MP stack 2 | 3 | ## Requirements 4 | 5 | * [Composer](https://getcomposer.org/download/) 6 | * [Vagrant](https://www.vagrantup.com/) >= 1.8 7 | * [Virtualbox](https://www.virtualbox.org/) 8 | * [Vagrant Hostsupdater](https://github.com/cogitatio/vagrant-hostsupdater) 9 | * [Vagrant Auto-network](https://github.com/oscar-stack/vagrant-auto_network) 10 | 11 | 12 | ## Quickstart 13 | 14 | ``` 15 | composer require --dev beet/box 16 | vagrant up 17 | ``` 18 | 19 | This will automatically generate a Vagrantfile and the `.beetbox` directory, which will contain a `config.yml` file used to configure overrides. 20 | 21 | You can see some examples in [`config.yml`](https://github.com/beetboxvm/beetbox/blob/master/.beetbox/config.yml) 22 | 23 | ## Drupal Quickstart 24 | 25 | To get a simple Drupal 8 site up and running with Beetbox, run the following commands: 26 | 27 | ``` 28 | composer create-project drupal-composer/drupal-project:8.x-dev drupal8 --stability dev --no-interaction 29 | cd drupal8 30 | composer require --dev beet/box 31 | vagrant up 32 | ``` 33 | 34 | After which you can install the site at [http://drupal8.local/install.php](http://drupal8.local/install.php) 35 | 36 | or add the following to `./beetbox/config.yml` and run `vagrant provision` to automatically install drupal. 37 | 38 | ``` 39 | drupal_install_site: yes 40 | drupal_account_name: admin 41 | drupal_account_pass: admin 42 | ``` 43 | 44 | For PHP 7 add `php_version: "7.0"` then `vagrant provision` 45 | -------------------------------------------------------------------------------- /docs/packer/builds.md: -------------------------------------------------------------------------------- 1 | # Building a base box 2 | 3 | beetbox builds are 100% automated, every commit to the master branch will trigger a new build of [`beet/dev`](https://atlas.hashicorp.com/beet). 4 | 5 | Therefore, `beet/dev` is the latest build and is used as the release candiate when creating new versions. 6 | 7 | # Creating a new version 8 | 9 | When a [new release](https://help.github.com/articles/creating-releases/) is made a tag is generated in the repo, this will trigger another CI run based on the tag. 10 | If the CI run completes successfully and notices a tag has been created it will trigger a new packer build of [`beet/box`](https://atlas.hashicorp.com/beet) on Atlas. 11 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | 11 | 12 | ./tests/ 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /provisioning/ansible/config/default.config.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # 3 | # Default Beetbox VM configuration. 4 | # 5 | # Settings below related to the Ansible roles from Galaxy. 6 | # Copy any of these settings to the custom config file to override. 7 | # 8 | 9 | # Vagrant config. 10 | vagrant_box: beet/box 11 | vagrant_box_version: "~> 0.8.0" 12 | vagrant_ip: "0.0.0.0" 13 | vagrant_memory: "1024" 14 | vagrant_cpus: 1 15 | 16 | # Beetbox config. 17 | beet_profile: beetbox 18 | beet_repo: "{{ lookup('env','BEET_REPO') | default('https://github.com/beetboxvm/beetbox.git',true) }}" 19 | beet_version: "{{ lookup('env','BEET_VERSION') | default('master',true) }}" 20 | beet_home: "/beetbox" 21 | beet_role_dir: "{{ beet_home }}/provisioning/ansible/roles" 22 | beet_project: drupal 23 | beet_debug: no 24 | beet_domain: "{{ ansible_hostname }}.local" 25 | beet_aliases: [] 26 | beet_env_name: BB_ENVIRONMENT 27 | beet_env: vagrant 28 | beet_user: "{{ lookup('env','BEET_USER') | default('vagrant',true) }}" 29 | beet_base: "/var/beetbox" 30 | beet_root: "{{ beet_base }}" 31 | beet_web: "{{ beet_root }}" 32 | beet_ssh_home: "{{ beet_root }}" 33 | beet_site_name: "Beetbox" 34 | beet_webserver: apache 35 | beet_mysql_user: beetbox 36 | beet_mysql_password: beetbox 37 | beet_mysql_database: "beetbox" 38 | beet_custom_pre_tasks: "{{ beet_base }}/.beetbox/tasks/pre" 39 | beet_custom_post_tasks: "{{ beet_base }}/.beetbox/tasks/post" 40 | beet_root_create: yes 41 | beet_provision_playbook: provision 42 | beet_provision_tags: all 43 | beet_provision: yes 44 | 45 | # Symlinks. 46 | symlinks: no 47 | 48 | # Known hosts. 49 | known_hosts: no 50 | 51 | # Apache config. 52 | apache_vhost_php_fpm_parameters: | 53 | 54 | SetHandler "proxy:fcgi://{{ php_fpm_listen }}" 55 | 56 | SetEnv {{ beet_env_name }} {{ beet_env }} 57 | apache_daemon: apache2 58 | apache_remove_default_vhost: true 59 | apache_listen_port: "{{ (beet_webserver == 'apache') | ternary('80','82') }}" 60 | apache_vhosts: 61 | - servername: "{{ beet_domain }}" 62 | documentroot: "{{ beet_web }}" 63 | extra_parameters: "{{ apache_vhost_php_fpm_parameters }}" 64 | apache_listen_port_ssl: "{{ (beet_webserver == 'apache') | ternary('443','444') }}" 65 | apache_vhosts_ssl: 66 | - servername: "{{ beet_domain }}" 67 | documentroot: "{{ beet_web }}" 68 | certificate_file: "/etc/ssl/certs/ssl-cert-snakeoil.pem" 69 | certificate_key_file: "/etc/ssl/private/ssl-cert-snakeoil.key" 70 | extra_parameters: "{{ apache_vhost_php_fpm_parameters }}" 71 | apache_mods_enabled: 72 | - authn_core.load 73 | - expires.load 74 | - ssl.load 75 | - rewrite.load 76 | - proxy.load 77 | - proxy_fcgi.load 78 | 79 | # Databases. 80 | mysql_databases: 81 | - name: "{{ beet_mysql_database }}" 82 | encoding: utf8 83 | collation: utf8_general_ci 84 | mysql_users: 85 | - name: "{{ beet_mysql_user }}" 86 | host: "%" 87 | password: "{{ beet_mysql_password }}" 88 | priv: "*.*:ALL" 89 | 90 | # Condintional roles. 91 | installed_extras_init: no 92 | installed_extras_adminer: no 93 | installed_extras_apache: no 94 | installed_extras_apparmor: no 95 | installed_extras_avahi: no 96 | installed_extras_composer: no 97 | installed_extras_drupal_console: no 98 | installed_extras_drush: no 99 | installed_extras_git: no 100 | installed_extras_mailhog: no 101 | installed_extras_memcached: no 102 | installed_extras_mysql: no 103 | installed_extras_nginx: no 104 | installed_extras_pecl: no 105 | installed_extras_php: no 106 | installed_extras_upload_progress: no 107 | installed_extras_web: no 108 | installed_extras_xdebug: no 109 | installed_extras_xhprof: no 110 | installed_extras_lxd: no 111 | installed_extras_chrome: no 112 | installed_extras_selenium: no 113 | installed_extras_elasticsearch: no 114 | installed_extras_firewall: no 115 | installed_extras_postfix: no 116 | installed_extras_platform_cli: no 117 | installed_extras_pantheon_cli: no 118 | installed_extras_varnish: no 119 | installed_extras_pimpmylog: no 120 | installed_extras_postgresql: no 121 | installed_extras_nodejs: no 122 | installed_extras_ruby: no 123 | installed_extras_rvm: no 124 | installed_extras_solr: no 125 | installed_extras_redis: no 126 | installed_extras_blackfire: no 127 | installed_extras_newrelic: no 128 | installed_extras_wp_cli: no 129 | installed_extras_phantomjs: no 130 | installed_extras_dcr: no 131 | 132 | # apt repositories. 133 | apt_repos: 134 | - ppa:ondrej/apache2 135 | - ppa:ondrej/php 136 | - ppa:ondrej/php5-compat 137 | 138 | # Extra packages. 139 | extra_packages: 140 | - imagemagick 141 | - unzip 142 | 143 | # git config. 144 | git_packages: 145 | - git 146 | 147 | # Varnish config. 148 | varnish_listen_port: 81 149 | varnish_storage: "malloc,256m" 150 | 151 | # Nodejs config. 152 | nodejs_install_npm_user: "{{ beet_user }}" 153 | npm_config_prefix: "/home/{{ beet_user }}/.npm-global" 154 | 155 | # Ruby config. 156 | ruby_install_gems_user: "vagrant" 157 | ruby_install_gems: [] 158 | 159 | # Nginx config. 160 | nginx_listen_port: "{{ (beet_webserver == 'nginx') | ternary('80','82') }}" 161 | nginx_php_fpm: /var/run/php5-fpm.sock 162 | nginx_remove_default_vhost: true 163 | nginx_hosts: 164 | - listen: "{{ nginx_listen_port }}" 165 | server_name: "{{ beet_domain }}" 166 | root: "{{ beet_web }}" 167 | is_php: true 168 | 169 | # PHP config. 170 | php_version: "7.1" 171 | php_install_recommends: no 172 | php_display_errors: "On" 173 | php_display_startup_errors: "On" 174 | php_realpath_cache_size: "1024K" 175 | php_sendmail_path: "/opt/mailhog/mhsendmail" 176 | php_opcache_enabled_in_ini: true 177 | php_opcache_memory_consumption: "192" 178 | php_max_input_vars: "4000" 179 | php_module_path: "/usr/lib/php{{ php_version }}/modules" 180 | php_enable_php_fpm: true 181 | php_fpm_listen: "127.0.0.1:9000" 182 | 183 | # Composer config. 184 | composer_home_path: '/home/{{ beet_user }}/.composer' 185 | composer_home_owner: "{{ beet_user }}" 186 | composer_home_group: "{{ beet_user }}" 187 | composer_global_packages: 188 | - name: hirak/prestissimo 189 | release: '^0.3' 190 | 191 | # Drush config. 192 | drush_install_from_source: yes 193 | drush_version: "8.x" 194 | drush_clone_depth: ~ 195 | drush_keep_updated: "{{ (drush_version != '8.x') }}" 196 | drush_create_alias: yes 197 | drush_alias_name: "{{ beet_domain }}" 198 | 199 | # MySQL config. 200 | mysql_port: "3306" 201 | mysql_root_password: "" 202 | mysql_slow_query_log_enabled: true 203 | mysql_wait_timeout: 300 204 | adminer_install_filename: index.php 205 | 206 | # XDebug config. 207 | php_xdebug_default_enable: 1 208 | php_xdebug_remote_enable: 1 209 | php_xdebug_remote_connect_back: 1 210 | php_xdebug_remote_host: "{{ ansible_default_ipv4.gateway }}" 211 | # IDE key for debug. 212 | php_xdebug_idekey: PHPSTORM 213 | # php_xdebug_idekey: sublime.xdebug 214 | php_xdebug_module_path: "{{ php_module_path }}" 215 | 216 | # Xhprof config. 217 | php_xhprof_module_path: "{{ php_module_path }}" 218 | 219 | # uploadprogress config. 220 | php_uploadprogress_module_path: "{{ php_module_path }}" 221 | 222 | # DCR config. 223 | dcr_install_dir: "{{ beet_root }}" 224 | 225 | # Other config. 226 | known_hosts_path: ~/.ssh/known_hosts 227 | workspace: "{{ beet_home }}/workspace/{{ php_version }}" 228 | welcome_template: "templates/welcome.txt.j2" 229 | -------------------------------------------------------------------------------- /provisioning/ansible/config/profiles/acquia/blt.config.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # 3 | # Acquia BLT profile - https://github.com/acquia/blt 4 | # 5 | 6 | # Project webroot. 7 | beet_root: "{{ beet_base }}/docroot" 8 | 9 | # Database config. 10 | beet_mysql_user: drupal 11 | beet_mysql_password: drupal 12 | beet_mysql_database: drupal 13 | 14 | # beetbox automatically creates a drush alias file in your ~/.drush folder if 15 | # this variable is 'true'. 16 | drush_create_alias: false 17 | 18 | php_version: '5.6' 19 | php_packages_extra: 20 | - php{{ php_version }}-bz2 21 | 22 | # This is required for front-end building tools. 23 | nodejs_version: "4.x" 24 | nodejs_npm_global_packages: 25 | - name: bower 26 | - name: gulp-cli 27 | nodejs_install_npm_user: "{{ beet_user }}" 28 | npm_config_prefix: "/home/{{ beet_user }}/.npm-global" 29 | 30 | # XDebug configuration. 31 | # Change this value to 1 in order to enable xdebug by default. 32 | php_xdebug_default_enable: 0 33 | php_xdebug_coverage_enable: 0 34 | # Change this value to 1 in order to enable xdebug on the cli. 35 | php_xdebug_cli_enable: 0 36 | php_xdebug_remote_enable: 1 37 | php_xdebug_remote_connect_back: 1 38 | # Use PHPSTORM for PHPStorm, sublime.xdebug for Sublime Text. 39 | php_xdebug_idekey: PHPSTORM 40 | php_xdebug_max_nesting_level: 256 41 | php_xdebug_remote_port: "9000" 42 | 43 | # PhantomJS. 44 | phantomjs_webdriver: yes 45 | phantomjs_webdriver_port: 4444 46 | -------------------------------------------------------------------------------- /provisioning/ansible/config/profiles/acquia/php5.6.config.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # 3 | # Acquia PHP 5.6 profile. 4 | # 5 | 6 | # Enabled roles. 7 | installed_extras_init: yes 8 | installed_extras_adminer: yes 9 | installed_extras_apache: yes 10 | installed_extras_apparmor: yes 11 | installed_extras_avahi: yes 12 | installed_extras_composer: yes 13 | installed_extras_drush: yes 14 | installed_extras_drupal_console: yes 15 | installed_extras_git: yes 16 | installed_extras_mailhog: yes 17 | installed_extras_memcached: yes 18 | installed_extras_mysql: yes 19 | installed_extras_nodejs: yes 20 | installed_extras_pecl: yes 21 | installed_extras_php: yes 22 | installed_extras_upload_progress: yes 23 | installed_extras_web: yes 24 | installed_extras_xdebug: yes 25 | installed_extras_xhprof: yes 26 | 27 | # Config. 28 | beet_root: "{{ beet_base }}/docroot" 29 | -------------------------------------------------------------------------------- /provisioning/ansible/config/profiles/beetbox.config.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # 3 | # Beetbox profile. 4 | # 5 | 6 | # Enabled roles. 7 | installed_extras_init: yes 8 | installed_extras_adminer: yes 9 | installed_extras_apache: yes 10 | installed_extras_apparmor: yes 11 | installed_extras_avahi: yes 12 | installed_extras_chrome: yes 13 | installed_extras_composer: yes 14 | installed_extras_drush: yes 15 | installed_extras_git: yes 16 | installed_extras_mailhog: yes 17 | installed_extras_memcached: yes 18 | installed_extras_mysql: yes 19 | installed_extras_nodejs: yes 20 | installed_extras_pecl: yes 21 | installed_extras_php: yes 22 | installed_extras_upload_progress: yes 23 | installed_extras_web: yes 24 | installed_extras_xdebug: yes 25 | 26 | # Conditional roles. 27 | installed_extras_nginx: "beet_webserver == 'nginx'" 28 | -------------------------------------------------------------------------------- /provisioning/ansible/config/profiles/pantheon/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beetboxvm/beetbox/b33fbf8e316ff4520deb95b6c3be1f6145d023bd/provisioning/ansible/config/profiles/pantheon/.gitkeep -------------------------------------------------------------------------------- /provisioning/ansible/config/profiles/platform.sh/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/beetboxvm/beetbox/b33fbf8e316ff4520deb95b6c3be1f6145d023bd/provisioning/ansible/config/profiles/platform.sh/.gitkeep -------------------------------------------------------------------------------- /provisioning/ansible/playbook-config.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | connection: local 4 | become: yes 5 | 6 | vars: 7 | beet_base: "{{ lookup('env','BEET_BASE') | default('/var/beetbox',true) }}" 8 | beet_user: "{{ lookup('env','BEET_USER') | default('vagrant',true) }}" 9 | beet_profile: "{{ lookup('env','BEET_PROFILE') | default('beetbox',true) }}" 10 | ansible_home: "{{ lookup('env','ANSIBLE_HOME') | default('/beetbox/provisioning/ansible',true) }}" 11 | conf_dir: "{{ beet_base }}/.beetbox" 12 | conf_files: 13 | - default.config.yml 14 | - "profiles/{{ beet_profile }}.config.yml" 15 | - project.config.yml 16 | - host.config.yml 17 | - config.yml 18 | - local.config.yml 19 | 20 | tasks: 21 | 22 | - name: Check if config files exists 23 | stat: "path={{ conf_dir }}/{{ item }}" 24 | with_items: "{{ conf_files }}" 25 | register: available_conf 26 | 27 | - name: Copy config files from config directory. 28 | copy: 29 | src: "{{ conf_dir }}/{{ item.item }}" 30 | dest: "{{ ansible_home }}/config/{{ item.item }}" 31 | force: yes 32 | when: item.stat.exists 33 | with_items: "{{ available_conf.results }}" 34 | changed_when: false 35 | 36 | - name: Create absent config files. 37 | file: 38 | path: "{{ ansible_home }}/config/{{ item }}" 39 | state: touch 40 | with_items: "{{ conf_files }}" 41 | changed_when: false 42 | 43 | - name: Check if playbook override directory exists 44 | stat: "path={{ conf_dir }}/playbooks" 45 | register: project_plays 46 | 47 | - name: Copy playbook overrides from config directory. 48 | copy: 49 | src: "{{ conf_dir }}/playbooks/" 50 | dest: "{{ ansible_home }}" 51 | force: yes 52 | when: project_plays.stat.exists 53 | changed_when: false 54 | 55 | - name: Check if project roles directory exists 56 | stat: "path={{ conf_dir }}/roles" 57 | register: project_roles 58 | 59 | - name: Copy project roles from config directory. 60 | copy: 61 | src: "{{ conf_dir }}/roles/" 62 | dest: "{{ ansible_home }}/roles" 63 | force: yes 64 | when: project_roles.stat.exists 65 | changed_when: false 66 | 67 | - name: "Ensure {{ beet_user }} has ownership of {{ ansible_home }}." 68 | file: 69 | path: "{{ ansible_home }}" 70 | owner: "{{ beet_user }}" 71 | group: "{{ beet_user }}" 72 | state: directory 73 | force: yes 74 | failed_when: false 75 | -------------------------------------------------------------------------------- /provisioning/ansible/playbook-provision.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | connection: local 4 | become: yes 5 | 6 | vars: 7 | beet_profile: "{{ lookup('env','BEET_PROFILE') | default('beetbox',true) }}" 8 | 9 | vars_files: 10 | - config/default.config.yml 11 | - "config/profiles/{{ beet_profile }}.config.yml" 12 | - config/project.config.yml 13 | - config/host.config.yml 14 | - config/config.yml 15 | - config/local.config.yml 16 | 17 | pre_tasks: 18 | 19 | - name: Check if index.php exists in beet_root. 20 | stat: 21 | path: "{{ beet_root }}/index.php" 22 | register: root_index_found 23 | 24 | - name: Get list of sub directories. 25 | find: 26 | paths: "{{ beet_base }}" 27 | file_type: directory 28 | register: sub_directories 29 | when: 30 | - beet_root == beet_base 31 | - not root_index_found.stat.exists 32 | 33 | - name: Look for index.php in project sub directories. 34 | stat: 35 | path: "{{ item.path }}/index.php" 36 | with_items: "{{ sub_directories.files }}" 37 | register: possible_root_paths 38 | when: 39 | - beet_root == beet_base 40 | - not root_index_found.stat.exists 41 | 42 | - name: Override beet_root if index.php found. 43 | set_fact: 44 | beet_root: "{{ item.item.path }}" 45 | with_items: "{{ possible_root_paths.results }}" 46 | when: 47 | - not root_index_found.stat.exists 48 | - beet_root == beet_base 49 | - item.stat.exists 50 | 51 | - name: Ensure pre tasks directory exists 52 | file: 53 | dest: "{{ beet_custom_pre_tasks }}" 54 | state: directory 55 | 56 | - include: "{{ item }}" 57 | with_fileglob: 58 | - "{{ beet_custom_pre_tasks }}/*" 59 | tags: 60 | - pre 61 | - custom 62 | 63 | roles: 64 | - role: beetbox-init 65 | when: installed_extras_init 66 | tags: beetbox 67 | - role: beetbox-known-hosts 68 | when: known_hosts 69 | tags: extras 70 | - role: beetbox-packages 71 | when: extra_packages 72 | tags: beetbox 73 | - role: beetbox-apt-repos 74 | when: apt_repos 75 | tags: beetbox 76 | - role: beetbox-symlinks 77 | when: symlinks 78 | tags: extras 79 | - role: geerlingguy.apache 80 | when: installed_extras_apache 81 | tags: beetbox 82 | - role: geerlingguy.apache-php-fpm 83 | when: installed_extras_php 84 | tags: beetbox 85 | - role: geerlingguy.nginx 86 | when: installed_extras_nginx 87 | tags: beetbox 88 | - role: geerlingguy.mysql 89 | when: installed_extras_mysql 90 | tags: beetbox 91 | - role: geerlingguy.php-versions 92 | when: installed_extras_php 93 | tags: beetbox 94 | - role: geerlingguy.php 95 | when: installed_extras_php 96 | tags: beetbox 97 | - role: geerlingguy.php-pecl 98 | when: installed_extras_pecl 99 | tags: beetbox 100 | - role: geerlingguy.php-mysql 101 | when: installed_extras_mysql 102 | tags: beetbox 103 | - role: geerlingguy.composer 104 | when: installed_extras_composer 105 | tags: beetbox 106 | - role: pwelch.avahi 107 | when: installed_extras_avahi 108 | - role: geerlingguy.firewall 109 | when: installed_extras_firewall 110 | tags: extras 111 | - role: geerlingguy.git 112 | when: installed_extras_git 113 | tags: extras 114 | - role: thebinary.lxd 115 | when: installed_extras_lxd 116 | tags: extras 117 | - role: ANXS.postgresql 118 | when: installed_extras_postgresql 119 | tags: extras 120 | - role: geerlingguy.memcached 121 | when: installed_extras_memcached 122 | tags: extras 123 | - role: geerlingguy.php-memcached 124 | when: installed_extras_memcached 125 | tags: extras 126 | - role: geerlingguy.drush 127 | when: installed_extras_drush 128 | tags: extras 129 | - role: geerlingguy.drupal-console 130 | when: installed_extras_drupal_console 131 | tags: extras 132 | - role: thom8.php-upload-progress 133 | when: installed_extras_upload_progress 134 | tags: extras 135 | - role: geerlingguy.php-xdebug 136 | when: installed_extras_xdebug 137 | tags: extras 138 | - role: geerlingguy.php-xhprof 139 | when: installed_extras_xhprof 140 | tags: extras 141 | - role: geerlingguy.blackfire 142 | when: installed_extras_blackfire 143 | tags: extras 144 | - role: geerlingguy.adminer 145 | when: installed_extras_adminer 146 | tags: extras 147 | - role: geerlingguy.pimpmylog 148 | when: installed_extras_pimpmylog 149 | tags: extras 150 | - role: geerlingguy.daemonize 151 | when: installed_extras_mailhog 152 | tags: extras 153 | - role: geerlingguy.postfix 154 | when: installed_extras_postfix 155 | tags: extras 156 | - role: geerlingguy.mailhog 157 | when: installed_extras_mailhog 158 | tags: extras 159 | - role: franklinkim.newrelic 160 | when: installed_extras_newrelic 161 | tags: extras 162 | - role: geerlingguy.nodejs 163 | when: installed_extras_nodejs 164 | tags: extras 165 | - role: geerlingguy.redis 166 | when: installed_extras_redis 167 | tags: extras 168 | - role: geerlingguy.php-redis 169 | when: installed_extras_redis 170 | tags: extras 171 | - role: geerlingguy.ruby 172 | when: installed_extras_ruby 173 | tags: extras 174 | - role: rvm_io.rvm1-ruby 175 | when: installed_extras_rvm 176 | tags: extras 177 | - role: geerlingguy.java 178 | when: installed_extras_solr or installed_extras_selenium or installed_extras_elasticsearch 179 | tags: extras 180 | - role: geerlingguy.solr 181 | when: installed_extras_solr 182 | tags: extras 183 | - role: cmprescott.chrome-fork 184 | when: installed_extras_chrome 185 | tags: extras 186 | - role: arknoll.selenium 187 | when: installed_extras_selenium 188 | tags: extras 189 | - role: geerlingguy.elasticsearch 190 | when: installed_extras_elasticsearch 191 | tags: extras 192 | - role: geerlingguy.varnish 193 | when: installed_extras_varnish 194 | tags: extras 195 | - role: pixelart.platformsh-cli 196 | when: installed_extras_platform_cli 197 | tags: extras 198 | - role: hashbangcode.pantheon-cli 199 | when: installed_extras_pantheon_cli 200 | tags: extras 201 | - role: beetboxvm.phantomjs 202 | when: installed_extras_phantomjs 203 | tags: extras 204 | - role: heskethm.wp-cli 205 | when: installed_extras_wp_cli 206 | tags: extras 207 | - role: alexdesignworks.dcr 208 | when: installed_extras_dcr 209 | tags: extras 210 | - role: beetboxvm.composer 211 | when: beet_project == 'composer' 212 | tags: project 213 | - role: beetboxvm.drupal 214 | when: beet_project == 'drupal' 215 | tags: project 216 | - role: beetboxvm.backdrop 217 | when: beet_project == 'backdrop' 218 | tags: project 219 | - role: beetboxvm.kohana 220 | when: beet_project == 'kohana' 221 | tags: project 222 | - role: beetboxvm.modx 223 | when: beet_project == 'modx' 224 | tags: project 225 | - role: beetboxvm.silverstripe 226 | when: beet_project == 'silverstripe' 227 | tags: project 228 | - role: beetboxvm.slim 229 | when: beet_project == 'slim' 230 | tags: project 231 | - role: beetboxvm.symfony 232 | when: beet_project == 'symfony' 233 | tags: project 234 | - role: beetboxvm.wordpress 235 | when: beet_project == 'wordpress' 236 | tags: project 237 | - role: beetbox-web 238 | when: installed_extras_web 239 | tags: beetbox 240 | - role: beetbox-apparmor 241 | when: installed_extras_apparmor 242 | tags: beetbox 243 | - role: beetbox-php-nginx 244 | when: installed_extras_nginx 245 | tags: beetbox 246 | 247 | tasks: 248 | 249 | - name: Set ownership of beet_user home directory. 250 | file: 251 | path: "/home/{{ beet_user }}" 252 | state: directory 253 | owner: "{{ beet_user }}" 254 | group: "{{ beet_user }}" 255 | recurse: yes 256 | 257 | - name: Ensure post tasks directory exists 258 | file: 259 | dest: "{{ beet_custom_post_tasks }}" 260 | state: directory 261 | 262 | - include: "{{ item }}" 263 | with_fileglob: 264 | - "{{ beet_custom_post_tasks }}/*" 265 | tags: 266 | - post 267 | - custom 268 | 269 | - name: Create welcome message. 270 | template: 271 | src: "{{ welcome_template }}" 272 | dest: "{{ beet_home }}/results-provision.txt" 273 | force: yes 274 | mode: 0644 275 | changed_when: no 276 | become: no 277 | 278 | - name: Create dynamic message of the day. 279 | template: 280 | dest: "/etc/update-motd.d/15-beetbox" 281 | src: "templates/motd.sh.j2" 282 | force: yes 283 | mode: 0755 284 | become: yes 285 | -------------------------------------------------------------------------------- /provisioning/ansible/playbook-setup.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | connection: local 4 | become: yes 5 | 6 | vars: 7 | beet_profile: "{{ lookup('env','BEET_PROFILE') | default('beetbox',true) }}" 8 | 9 | vars_files: 10 | - config/default.config.yml 11 | - "config/profiles/{{ beet_profile }}.config.yml" 12 | - config/project.config.yml 13 | - config/host.config.yml 14 | - config/config.yml 15 | - config/local.config.yml 16 | 17 | roles: 18 | - { role: beetbox-docker, when: ansible_virtualization_type != 'virtualbox' } 19 | - { role: beetbox-vagrant } 20 | - { role: beetbox-ubuntu } 21 | - { role: beetbox-virtualbox, when: ansible_virtualization_type == 'virtualbox' } 22 | - { role: beetbox-packer } 23 | -------------------------------------------------------------------------------- /provisioning/ansible/roles/beetbox-apparmor/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Check if AppArmor service exists 3 | stat: 4 | path: /etc/init.d/apparmor 5 | register: apparmor_service_status 6 | 7 | - name: Ensure MySQL AppArmor profile is disabled (for slow query log). 8 | file: 9 | path: /etc/apparmor.d/disable/usr.sbin.mysqld 10 | src: /etc/apparmor.d/usr.sbin.mysqld 11 | state: link 12 | register: mysql_apparmor 13 | when: mysql_slow_query_log_enabled and apparmor_service_status.stat.exists 14 | 15 | - name: Restart AppArmor if necessary. 16 | service: 17 | name: apparmor 18 | state: restarted 19 | when: mysql_apparmor.changed 20 | -------------------------------------------------------------------------------- /provisioning/ansible/roles/beetbox-apt-repos/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Add apt repositories (if any are configured). 3 | apt_repository: 4 | repo: "{{ item }}" 5 | mode: 644 6 | update_cache: yes 7 | with_items: "{{ apt_repos }}" 8 | when: apt_repos 9 | -------------------------------------------------------------------------------- /provisioning/ansible/roles/beetbox-docker/files/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Start supervisor 4 | supervisord -n -c /etc/supervisor/conf.d/supervisord.conf 5 | -------------------------------------------------------------------------------- /provisioning/ansible/roles/beetbox-docker/files/supervisord.conf: -------------------------------------------------------------------------------- 1 | [supervisord] 2 | nodaemon=true 3 | logfile=/tmp/supervisord.log 4 | logfile_maxbytes=50MB 5 | logfile_backups=10 6 | loglevel=info 7 | pidfile=/tmp/supervisord.pid 8 | 9 | [program:sshd] 10 | command=/usr/sbin/sshd -D 11 | 12 | [program:mysqld] 13 | command=/usr/bin/mysqld_safe --skip-syslog 14 | 15 | [program:php7-fpm] 16 | command = /usr/sbin/php-fpm7.1 -F 17 | 18 | [program:apache2] 19 | command=/usr/sbin/apache2ctl -D FOREGROUND 20 | -------------------------------------------------------------------------------- /provisioning/ansible/roles/beetbox-docker/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Ensure apt cache is updated. 3 | apt: update_cache=yes cache_valid_time=3600 4 | 5 | - name: Install docker packages 6 | apt: "name={{ item }} state=installed" 7 | with_items: 8 | - mysql-server 9 | - openssh-server 10 | - supervisor 11 | - python-pycurl 12 | - build-essential 13 | - unzip 14 | 15 | - name: Ensure directories exists. 16 | file: 17 | path: "{{ item }}" 18 | state: directory 19 | mode: 0644 20 | with_items: 21 | - /var/log/supervisor 22 | - /var/run/sshd 23 | - /run/php 24 | 25 | - name: Add supervisor configuration. 26 | copy: 27 | src: supervisord.conf 28 | dest: /etc/supervisor/conf.d/supervisord.conf 29 | owner: root 30 | group: root 31 | mode: 0644 32 | 33 | - name: Add docker startup script. 34 | copy: 35 | src: start.sh 36 | dest: /start.sh 37 | owner: root 38 | group: root 39 | mode: 0755 40 | 41 | - name: Start MySQL service. 42 | command: "service mysql start" 43 | -------------------------------------------------------------------------------- /provisioning/ansible/roles/beetbox-init/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Set hostname. 3 | hostname: 4 | name: "{{ beet_domain }}" 5 | failed_when: false 6 | 7 | - name: Add domains and aliases to hosts file. 8 | lineinfile: 9 | dest: /etc/hosts 10 | regexp: '^127\.0\.0\.1' 11 | line: "127.0.0.1 localhost {{ beet_domain }} {{ beet_aliases | join(' ') }}" 12 | owner: root 13 | group: root 14 | mode: 0644 15 | failed_when: false 16 | 17 | - name: Update apt cache if needed. 18 | apt: 19 | update_cache: yes 20 | cache_valid_time: 3600 21 | 22 | - name: Get software for Python-based control. 23 | apt: "name={{ item }} state=installed" 24 | with_items: 25 | - curl 26 | - python-apt 27 | - python-httplib2 28 | - python-pycurl 29 | - build-essential 30 | 31 | - name: Disable the ufw firewall (since we use a simple iptables firewall). 32 | service: name=ufw state=stopped 33 | failed_when: false 34 | 35 | - name: Ensure beet_base directory exists. 36 | file: 37 | path: "{{ beet_base }}" 38 | state: directory 39 | mode: 0775 40 | 41 | - name: Ensure beet_root directory exists. 42 | file: 43 | path: "{{ beet_root }}" 44 | state: directory 45 | mode: 0775 46 | become: no 47 | 48 | - name: Ensure workspace directory exists. 49 | file: 50 | path: "{{ workspace }}" 51 | state: directory 52 | mode: 0775 53 | 54 | - name: Set SSH home directory. 55 | lineinfile: 56 | dest: "/home/{{ beet_user }}/.bashrc" 57 | state: present 58 | create: yes 59 | regexp: "^SSH_HOME=" 60 | line: "SSH_HOME={{ beet_ssh_home }} && [ -e $SSH_HOME ] && cd $SSH_HOME" 61 | become: no 62 | -------------------------------------------------------------------------------- /provisioning/ansible/roles/beetbox-known-hosts/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Ensure known hosts exist 3 | known_hosts: 4 | path: "{{ known_hosts_path }}" 5 | name: "{{ item }}" 6 | key: "{{ lookup('pipe', 'ssh-keyscan -t rsa ' + item) }}" 7 | with_items: "{{ known_hosts }}" 8 | become: no 9 | -------------------------------------------------------------------------------- /provisioning/ansible/roles/beetbox-packages/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install extra apt packages (if any are configured). 3 | apt: "name={{ item }} state=installed" 4 | with_items: "{{ extra_packages }}" 5 | when: extra_packages 6 | -------------------------------------------------------------------------------- /provisioning/ansible/roles/beetbox-packer/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | packer_version: 1.1.0 3 | packer_url: https://releases.hashicorp.com/packer/{{ packer_version }}/packer_{{ packer_version }}_linux_amd64.zip 4 | packer_install_dir: /usr/local/bin 5 | packer_templates: [] 6 | -------------------------------------------------------------------------------- /provisioning/ansible/roles/beetbox-packer/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Ensure unzip is installed. 3 | apt: 4 | name: "unzip" 5 | state: installed 6 | 7 | - name: Install Packer 8 | unarchive: 9 | src: "https://releases.hashicorp.com/packer/{{ packer_version }}/packer_{{ packer_version }}_linux_amd64.zip" 10 | dest: "{{ packer_install_dir }}" 11 | copy: no 12 | creates: "{{ packer_install_dir }}/packer" 13 | -------------------------------------------------------------------------------- /provisioning/ansible/roles/beetbox-php-nginx/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | nginx_vhost_path: /etc/nginx/sites-enabled 3 | -------------------------------------------------------------------------------- /provisioning/ansible/roles/beetbox-php-nginx/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Check for default nginx vhosts. 3 | stat: "path={{ nginx_vhost_path }}//{{ beet_domain }}.conf" 4 | register: nginx_default_vhost_conf 5 | 6 | - name: Copy default Nginx vhosts into place. 7 | template: 8 | src: nginx-vhost.conf.j2 9 | dest: "{{ nginx_vhost_path }}/{{ item.server_name }}.conf" 10 | force: yes 11 | owner: root 12 | group: root 13 | mode: 0644 14 | with_items: "{{ nginx_hosts }}" 15 | notify: restart nginx 16 | when: not nginx_default_vhost_conf.stat.exists 17 | -------------------------------------------------------------------------------- /provisioning/ansible/roles/beetbox-php-nginx/templates/nginx-vhost.conf.j2: -------------------------------------------------------------------------------- 1 | {% if item.server_name_redirect is defined %} 2 | server { 3 | listen 80; 4 | server_name {{ item.server_name_redirect }}; 5 | return 301 http://{{ item.server_name }}$request_uri; 6 | } 7 | {% endif %} 8 | 9 | server { 10 | listen {{ item.listen | default("80") }}; 11 | 12 | server_name {{ item.server_name }}; 13 | error_log /var/log/nginx/error.log info; 14 | root {{ item.root }}; 15 | index index.php index.html index.htm; 16 | 17 | {% if item.is_php is defined and item.is_php %} 18 | location / { 19 | try_files $uri $uri/ = 404; 20 | } 21 | 22 | error_page 404 /404.html; 23 | error_page 500 502 503 504 /50x.html; 24 | location = /50x.html { 25 | root /usr/share/nginx/html; 26 | } 27 | 28 | # Use fastcgi for all php files. 29 | location ~ \.php$ { 30 | # Secure *.php files. 31 | try_files $uri = 404; 32 | fastcgi_split_path_info ^(.+\.php)(/.+)$; 33 | 34 | fastcgi_pass unix:{{ nginx_php_fpm }}; 35 | fastcgi_index index.php; 36 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 37 | fastcgi_intercept_errors on; 38 | fastcgi_read_timeout 120; 39 | include fastcgi_params; 40 | } 41 | {% endif %} 42 | } 43 | -------------------------------------------------------------------------------- /provisioning/ansible/roles/beetbox-symlinks/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Ensure symlink dest is empty. 3 | file: 4 | path: "{{ item.link }}" 5 | state: absent 6 | when: "{{ item.force | default('false') }}" 7 | with_items: "{{ symlinks }}" 8 | 9 | - name: Create symlinks. 10 | file: 11 | src: "{{ item.src }}" 12 | dest: "{{ item.link }}" 13 | state: link 14 | with_items: "{{ symlinks }}" 15 | -------------------------------------------------------------------------------- /provisioning/ansible/roles/beetbox-ubuntu/files/refresh-apt.conf: -------------------------------------------------------------------------------- 1 | description "update package index" 2 | start on networking 3 | task 4 | exec /usr/bin/apt-get update 5 | -------------------------------------------------------------------------------- /provisioning/ansible/roles/beetbox-ubuntu/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Ensure apt cache is updated. 3 | apt: update_cache=yes cache_valid_time=3600 4 | 5 | - name: Disable release upgrade prompt. 6 | lineinfile: 7 | dest: /etc/update-manager/release-upgrades 8 | regexp: "^Prompt" 9 | line: "Prompt=never" 10 | owner: root 11 | group: root 12 | mode: 0644 13 | failed_when: false 14 | 15 | - name: Disbale failsafe boot. 16 | lineinfile: 17 | dest: /etc/init/rc-sysinit.conf 18 | regexp: "^start on" 19 | line: "start on (filesystem) or failsafe-boot" 20 | owner: root 21 | group: root 22 | mode: 0644 23 | failed_when: false 24 | 25 | - name: Add configuration to update apt cache on boot. 26 | copy: 27 | src: refresh-apt.conf 28 | dest: /etc/init/refresh-apt.conf 29 | owner: root 30 | group: root 31 | mode: 0644 32 | 33 | - name: Configure SSH daemon. 34 | lineinfile: 35 | dest: /etc/ssh/sshd_config 36 | regexp: "{{ item.regexp }}" 37 | line: "{{ item.line }}" 38 | state: present 39 | with_items: 40 | - { regexp: '^UseDNS', line: 'UseDNS no' } 41 | - { regexp: '^GSSAPIAuthentication', line: 'GSSAPIAuthentication no' } 42 | -------------------------------------------------------------------------------- /provisioning/ansible/roles/beetbox-vagrant/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Create vagrant user. 3 | user: 4 | name: vagrant 5 | shell: /bin/bash 6 | createhome: yes 7 | home: "/home/vagrant" 8 | 9 | - name: Ensure necessary groups exist. 10 | group: "name={{ item }} state=present" 11 | with_items: 12 | - admin 13 | - dialout 14 | 15 | - name: Set up sudo. 16 | lineinfile: 17 | dest: /etc/sudoers.d/vagrant 18 | state: present 19 | create: yes 20 | regexp: "^vagrant ALL" 21 | line: "vagrant ALL=(ALL) NOPASSWD:ALL" 22 | validate: "visudo -cf %s" 23 | mode: 0440 24 | 25 | - name: Configure Vagrant .ssh directory. 26 | file: 27 | path: /home/vagrant/.ssh 28 | state: directory 29 | owner: vagrant 30 | group: vagrant 31 | mode: 0700 32 | 33 | - name: Get Vagrant's public key. 34 | get_url: 35 | url: https://github.com/mitchellh/vagrant/raw/master/keys/vagrant.pub 36 | dest: /home/vagrant/.ssh/authorized_keys 37 | owner: vagrant 38 | group: vagrant 39 | mode: 0600 40 | 41 | - name: Fix stdin not being a tty. 42 | lineinfile: 43 | dest: /root/.profile 44 | regexp: "^mesg n" 45 | line: "tty -s && mesg n" 46 | owner: root 47 | group: root 48 | mode: 0644 49 | -------------------------------------------------------------------------------- /provisioning/ansible/roles/beetbox-virtualbox/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Get current kernel version. 3 | shell: uname -r 4 | register: current_kernel 5 | 6 | - name: Ensure correct kernel headers are installed. 7 | apt: 8 | name: "linux-headers-{{ current_kernel.stdout }}" 9 | state: installed 10 | 11 | # VirtualBox tools installation. 12 | - name: Check if VirtualBox is running the guest VM. 13 | stat: path=/home/vagrant/.vbox_version 14 | register: virtualbox_check 15 | 16 | - include: virtualbox.yml 17 | when: virtualbox_check.stat.exists 18 | -------------------------------------------------------------------------------- /provisioning/ansible/roles/beetbox-virtualbox/tasks/virtualbox.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Get VirtualBox version. 3 | shell: cat /home/vagrant/.vbox_version 4 | register: virtualbox_version 5 | 6 | - name: Check for VirtualBox guest additions ISO. 7 | stat: "path=/home/vagrant/VBoxGuestAdditions_{{ virtualbox_version.stdout }}.iso" 8 | register: virtualbox_iso 9 | 10 | - name: Download VirtualBox guest additions ISO. 11 | get_url: 12 | url: "http://download.virtualbox.org/virtualbox/{{ virtualbox_version.stdout }}/VBoxGuestAdditions_{{ virtualbox_version.stdout }}.iso" 13 | dest: "/home/vagrant/VBoxGuestAdditions_{{ virtualbox_version.stdout }}.iso" 14 | when: not virtualbox_iso.stat.exists 15 | 16 | - name: Mount VirtualBox guest additions ISO. 17 | mount: 18 | name: /tmp/vbox 19 | src: "/home/vagrant/VBoxGuestAdditions_{{ virtualbox_version.stdout }}.iso" 20 | opts: loop 21 | state: mounted 22 | fstype: iso9660 23 | 24 | - name: Run VirtualBox guest additions installation. 25 | shell: sh /tmp/vbox/VBoxLinuxAdditions.run 26 | failed_when: false 27 | 28 | - name: Unmount VirtualBox guest additions ISO. 29 | mount: 30 | name: /tmp/vbox 31 | src: "/home/vagrant/VBoxGuestAdditions_{{ virtualbox_version.stdout }}.iso" 32 | state: absent 33 | fstype: iso9660 34 | 35 | - name: Delete VirtualBox guest additions ISO. 36 | file: 37 | path: "/home/vagrant/VBoxGuestAdditions_{{ virtualbox_version.stdout }}.iso" 38 | state: absent 39 | -------------------------------------------------------------------------------- /provisioning/ansible/roles/beetbox-web/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Ensure www-data user is in dialout group. 3 | user: 4 | name: "www-data" 5 | append: yes 6 | groups: "dialout" 7 | 8 | - name: Set nicer permissions on Apache log directory. 9 | file: 10 | path: "/var/log/{{ apache_daemon }}" 11 | state: directory 12 | mode: 0755 13 | recurse: yes 14 | 15 | - name: Set tmp folder permissions. 16 | file: 17 | path: "/tmp" 18 | state: directory 19 | owner: root 20 | group: root 21 | mode: 0777 22 | -------------------------------------------------------------------------------- /provisioning/ansible/templates/motd.sh.j2: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [ -f "{{ beet_home }}/.beetbox/results-provision.txt" ]; then 3 | sed '1d;s/^/ /' {{ beet_home }}/.beetbox/results-provision.txt 4 | fi 5 | -------------------------------------------------------------------------------- /provisioning/ansible/templates/welcome.txt.j2: -------------------------------------------------------------------------------- 1 | ******************************************************************************** 2 | 3 | 4 | 888 888 888 5 | 888 888 888 6 | 888 888 888 7 | 88888b. .d88b. .d88b. 888888 88888b. .d88b. 888 888 8 | 888 "88b d8P Y8b d8P Y8b 888 888 "88b d88""88b `Y8bd8P' 9 | 888 888 88888888 88888888 888 888 888 888 888 X88K 10 | 888 d88P Y8b. Y8b. Y88b. 888 d88P Y88..88P .d8""8b. 11 | 88888P" "Y8888 "Y8888 "Y888 88888P" "Y88P" 888 888 12 | 13 | ------------------------------------------------------------ 14 | URL: http://{{ beet_domain }}/ 15 | ------------------------------------------------------------ 16 | 17 | MySQL 18 | ------------------------------------------------------------ 19 | Hostname: localhost or 127.0.0.1 20 | Port: {{ mysql_port }} 21 | Database name: {{ beet_mysql_database }} 22 | Username: {{ beet_mysql_user }} 23 | Password: {{ beet_mysql_password }} 24 | 25 | {% if (beet_project == 'drupal') %} 26 | Drupal 27 | ------------------------------------------------------------ 28 | {% if (drush_create_alias) %} 29 | Drush alias: @{{ drush_alias_name }} 30 | {% endif %} 31 | {% if (drupal_drush_login is defined and drupal_drush_login.rc == 0) %} 32 | Login link: {{ drupal_drush_login.stdout }} 33 | {% endif %} 34 | {% endif %} 35 | 36 | Developer Tools 37 | ------------------------------------------------------------ 38 | {% if (installed_extras_mailhog) %} 39 | Mailhog: http://{{ beet_domain }}:8025/ 40 | {% endif %} 41 | 42 | ------------------------------------------------------------ 43 | Documentation: http://beetbox.rtfd.org 44 | ------------------------------------------------------------ 45 | 46 | 47 | -------------------------------------------------------------------------------- /provisioning/beetbox.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -eu 2 | 3 | # Set default environment variables. 4 | export BEET_PROFILE=${BEET_PROFILE:-beetbox} 5 | BEET_PLAYBOOK=${BEET_PLAYBOOK:-provision} 6 | BEET_TAGS=${BEET_TAGS:-all} 7 | BEET_HOME=${BEET_HOME:-"/beetbox"} 8 | BEET_BASE=${BEET_BASE:-"/var/beetbox"} 9 | BEET_USER=${BEET_USER:-"vagrant"} 10 | BEET_REPO=${BEET_REPO:-"https://github.com/beetboxvm/beetbox.git"} 11 | BEET_VERSION=${BEET_VERSION:-"master"} 12 | BEET_DEBUG=${BEET_DEBUG:-false} 13 | ANSIBLE_HOME="$BEET_HOME/provisioning/ansible" 14 | ANSIBLE_DEBUG="" 15 | 16 | # Ansible config. 17 | export DISPLAY_SKIPPED_HOSTS=${DISPLAY_SKIPPED_HOSTS:-False} 18 | export ANSIBLE_DEPRECATION_WARNINGS=${ANSIBLE_DEPRECATION_WARNINGS:-False} 19 | export ANSIBLE_REMOTE_TEMP=${ANSIBLE_REMOTE_TEMP:-/tmp} 20 | export ANSIBLE_RETRY_FILES_ENABLED=${ANSIBLE_RETRY_FILES_ENABLED:-False} 21 | export ANSIBLE_FORCE_COLOR=${ANSIBLE_FORCE_COLOR:-True} 22 | export ANSIBLE_INVENTORY=${ANSIBLE_INVENTORY:-"localhost,"} 23 | export PYTHONUNBUFFERED=${PYTHONUNBUFFERED:-True} 24 | 25 | # Enable debug mode? 26 | if [[ "$BEET_DEBUG" = "true" ]]; then 27 | export ANSIBLE_DEPRECATION_WARNINGS=True 28 | ANSIBLE_DEBUG="-vvv" 29 | fi 30 | 31 | beetbox_setup() { 32 | # Install sudo in docker. 33 | [[ -f /.dockerenv ]] && apt-get -qq update && apt-get install -y sudo && rm -rf /var/lib/apt/lists/* 34 | 35 | # Create BEET_USER and setup sudo. 36 | [[ -z "$(getent passwd "$BEET_USER")" ]] && sudo useradd -d "/home/$BEET_USER" -m "$BEET_USER" > /dev/null 2>&1 37 | echo "$BEET_USER ALL=(ALL) NOPASSWD: ALL" | sudo tee "/etc/sudoers.d/$BEET_USER" > /dev/null 2>&1 38 | 39 | # Install ansible. 40 | if [[ ! -d "/etc/ansible" ]]; then 41 | sudo apt-get -qq update 42 | sudo apt-get -y install software-properties-common 43 | sudo apt-add-repository -y ppa:ansible/ansible 44 | sudo apt-get -qq update 45 | sudo apt-get -y install ansible 46 | fi 47 | 48 | # Clone beetbox if BEET_HOME doesn't exist. 49 | if [[ ! -d "$BEET_HOME" ]]; then 50 | beetbox_adhoc apt "name=git state=installed" 51 | beetbox_adhoc git "repo=$BEET_REPO version=$BEET_VERSION dest=$BEET_HOME depth=1 recursive=yes" 52 | beetbox_adhoc file "path=$BEET_HOME owner=$BEET_USER group=$BEET_USER" 53 | beetbox_adhoc file "path=$BEET_HOME/.beetbox/config.yml state=absent" 54 | beetbox_adhoc file "src=$BEET_HOME/provisioning/beetbox.sh dest=/usr/local/bin/beetbox state=link mode=755" 55 | [[ ! -d "$BEET_HOME" ]] && exit 1 56 | fi 57 | 58 | # Check version. 59 | beetbox_play config 60 | 61 | # Beetbox setup. 62 | beetbox_play setup 63 | 64 | # Create $BEET_HOME/.beetbox_installed 65 | beetbox_adhoc file "path=$BEET_HOME/installed state=touch" 66 | } 67 | 68 | beetbox_adhoc() { 69 | ansible localhost ${ANSIBLE_DEBUG} -m "${1}" -a "${2}" --become -c local -i localhost, 70 | } 71 | 72 | beetbox_play() { 73 | ansible-playbook "${ANSIBLE_HOME}/playbook-${1}.yml" ${ANSIBLE_DEBUG} -c local -i localhost, --tags "${2:-all}" 74 | } 75 | 76 | # Initialise beetbox. 77 | [[ ! -f "$BEET_HOME/installed" ]] && beetbox_setup 78 | 79 | # Create default config files. 80 | beetbox_play config 81 | 82 | # Provision VM. 83 | beetbox_play "$BEET_PLAYBOOK" "$BEET_TAGS" 84 | 85 | # Print welcome message. 86 | sudo touch "$BEET_HOME/results-$BEET_PLAYBOOK.txt" 87 | sudo cat "$BEET_HOME/results-$BEET_PLAYBOOK.txt" 88 | -------------------------------------------------------------------------------- /provisioning/packer/http/preseed.cfg: -------------------------------------------------------------------------------- 1 | choose-mirror-bin mirror/http/proxy string 2 | d-i base-installer/kernel/override-image string linux-server 3 | d-i clock-setup/utc boolean true 4 | d-i clock-setup/utc-auto boolean true 5 | d-i finish-install/reboot_in_progress note 6 | d-i grub-installer/only_debian boolean true 7 | d-i grub-installer/with_other_os boolean true 8 | d-i partman-auto-lvm/guided_size string max 9 | d-i partman-auto/choose_recipe select atomic 10 | d-i partman-auto/method string lvm 11 | d-i partman-lvm/confirm boolean true 12 | d-i partman-lvm/confirm_nooverwrite boolean true 13 | d-i partman-lvm/device_remove_lvm boolean true 14 | d-i partman/choose_partition select finish 15 | d-i partman/confirm boolean true 16 | d-i partman/confirm_nooverwrite boolean true 17 | d-i partman/confirm_write_new_label boolean true 18 | d-i pkgsel/include string openssh-server cryptsetup build-essential libssl-dev libreadline-dev zlib1g-dev linux-source dkms nfs-common 19 | d-i pkgsel/install-language-support boolean false 20 | d-i pkgsel/update-policy select none 21 | d-i pkgsel/upgrade select full-upgrade 22 | d-i time/zone string UTC 23 | tasksel tasksel/first multiselect standard, ubuntu-server 24 | 25 | d-i console-setup/ask_detect boolean false 26 | d-i keyboard-configuration/layoutcode string us 27 | d-i keyboard-configuration/modelcode string pc105 28 | d-i debian-installer/locale string en_US 29 | 30 | # Create vagrant user account. 31 | d-i passwd/user-fullname string vagrant 32 | d-i passwd/username string vagrant 33 | d-i passwd/user-password password vagrant 34 | d-i passwd/user-password-again password vagrant 35 | d-i user-setup/allow-password-weak boolean true 36 | d-i user-setup/encrypt-home boolean false 37 | d-i passwd/user-default-groups vagrant sudo 38 | d-i passwd/user-uid string 900 39 | 40 | d-i preseed/late_command string \ 41 | echo 'Defaults:vagrant !requiretty' > /target/etc/sudoers.d/vagrant; \ 42 | echo 'vagrant ALL=(ALL) NOPASSWD: ALL' >> /target/etc/sudoers.d/vagrant; \ 43 | chmod 440 /target/etc/sudoers.d/vagrant; \ 44 | in-target update-initramfs -u 45 | -------------------------------------------------------------------------------- /provisioning/packer/scripts/cleanup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -eux 2 | 3 | # Make sure udev does not block our network - http://6.ptmc.org/?p=164 4 | echo "==> Cleaning up udev rules" 5 | rm -rf /dev/.udev/ 6 | rm /lib/udev/rules.d/75-persistent-net-generator.rules 7 | 8 | echo "==> Cleaning up leftover dhcp leases" 9 | # Ubuntu 10.04 10 | if [ -d "/var/lib/dhcp3" ]; then 11 | rm /var/lib/dhcp3/* 12 | fi 13 | # Ubuntu 12.04 & 14.04 14 | if [ -d "/var/lib/dhcp" ]; then 15 | rm /var/lib/dhcp/* 16 | fi 17 | 18 | # Add delay to prevent "vagrant reload" from failing 19 | echo "pre-up sleep 2" >> /etc/network/interfaces 20 | 21 | echo "==> Cleaning up tmp" 22 | rm -rf /tmp/* 23 | 24 | # Cleanup apt cache 25 | apt-get -y autoremove --purge 26 | apt-get -y clean 27 | apt-get -y autoclean 28 | 29 | echo "==> Installed packages" 30 | dpkg --get-selections | grep -v deinstall 31 | 32 | DISK_USAGE_BEFORE_CLEANUP=$(df -h) 33 | 34 | # Remove Bash history 35 | unset HISTFILE 36 | rm -f /root/.bash_history 37 | rm -f /home/vagrant/.bash_history 38 | 39 | # Clean up log files 40 | find /var/log -type f | while read f; do echo -ne '' > $f; done; 41 | 42 | echo "==> Clearing last login information" 43 | >/var/log/lastlog 44 | >/var/log/wtmp 45 | >/var/log/btmp 46 | 47 | # Whiteout root 48 | count=$(df --sync -kP / | tail -n1 | awk -F ' ' '{print $4}') 49 | let count-- 50 | dd if=/dev/zero of=/tmp/whitespace bs=1024 count=$count 51 | rm /tmp/whitespace 52 | 53 | # Whiteout /boot 54 | count=$(df --sync -kP /boot | tail -n1 | awk -F ' ' '{print $4}') 55 | let count-- 56 | dd if=/dev/zero of=/boot/whitespace bs=1024 count=$count 57 | rm /boot/whitespace 58 | 59 | echo '==> Clear out swap and disable until reboot' 60 | set +e 61 | swapuuid=$(/sbin/blkid -o value -l -s UUID -t TYPE=swap) 62 | case "$?" in 63 | 2|0) ;; 64 | *) exit 1 ;; 65 | esac 66 | set -e 67 | if [ "x${swapuuid}" != "x" ]; then 68 | # Whiteout the swap partition to reduce box size 69 | # Swap is disabled till reboot 70 | swappart=$(readlink -f /dev/disk/by-uuid/$swapuuid) 71 | /sbin/swapoff "${swappart}" 72 | dd if=/dev/zero of="${swappart}" bs=1M || echo "dd exit code $? is suppressed" 73 | /sbin/mkswap -U "${swapuuid}" "${swappart}" 74 | fi 75 | 76 | # Delete beet_base. 77 | rm -rf /var/beetbox 78 | 79 | # Clean the APT directory. 80 | rm -rf /var/lib/apt/lists/* 81 | 82 | # Invalidate APT cache. 83 | rm -rf /var/lib/apt/periodic/update-success-stamp 84 | touch -d "2 days ago" /var/lib/apt/lists 85 | 86 | # Zero out the free space to save space in the final image 87 | dd if=/dev/zero of=/EMPTY bs=1M || echo "dd exit code $? is suppressed" 88 | rm -f /EMPTY 89 | 90 | # Make sure we wait until all the data is written to disk, otherwise 91 | # Packer might quite too early before the large files are deleted 92 | sync 93 | 94 | echo "==> Disk usage before cleanup" 95 | echo ${DISK_USAGE_BEFORE_CLEANUP} 96 | 97 | echo "==> Disk usage after cleanup" 98 | df -h 99 | -------------------------------------------------------------------------------- /provisioning/packer/scripts/minimize.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -eux 2 | 3 | echo "==> Disk usage before minimization" 4 | df -h 5 | 6 | echo "==> Installed packages before cleanup" 7 | dpkg --get-selections | grep -v deinstall 8 | 9 | # Remove some packages to get a minimal install 10 | echo "==> Removing all linux kernels except the currrent one" 11 | dpkg --list | awk '{ print $2 }' | grep 'linux-image-3.*-generic' | grep -v $(uname -r) | xargs apt-get -y purge 12 | echo "==> Removing linux source" 13 | dpkg --list | awk '{ print $2 }' | grep linux-source | xargs apt-get -y purge 14 | echo "==> Removing documentation" 15 | dpkg --list | awk '{ print $2 }' | grep -- '-doc$' | xargs apt-get -y purge 16 | echo "==> Removing obsolete networking components" 17 | apt-get -y purge ppp pppconfig pppoeconf 18 | echo "==> Removing other oddities" 19 | apt-get -y purge popularity-contest installation-report landscape-common wireless-tools wpasupplicant 20 | 21 | # Clean up the apt cache 22 | apt-get -y autoremove --purge 23 | apt-get -y autoclean 24 | apt-get -y clean 25 | 26 | # Clean up orphaned packages with deborphan 27 | apt-get -y install deborphan 28 | 29 | while [ -n "$(deborphan --guess-all --no-guess-dev --no-guess-python --libdevel)" ]; do 30 | deborphan --guess-all --no-guess-dev --no-guess-python --libdevel| xargs apt-get -y purge 31 | done 32 | apt-get -y purge deborphan dialog 33 | 34 | echo "==> Removing man pages" 35 | rm -rf /usr/share/man/* 36 | echo "==> Removing APT files" 37 | find /var/lib/apt -type f | xargs rm -f 38 | echo "==> Removing any docs" 39 | rm -rf /usr/share/doc/* 40 | echo "==> Removing caches" 41 | find /var/cache -type f -exec rm -rf {} \; 42 | 43 | echo "==> Disk usage after cleanup" 44 | df -h 45 | -------------------------------------------------------------------------------- /provisioning/ubuntu-16.04.json: -------------------------------------------------------------------------------- 1 | { 2 | "variables": { 3 | "cloud_build_name": "dev", 4 | "cloud_username": "beet", 5 | "cloud_token": "", 6 | "beet_repo": "https://github.com/beetboxvm/beetbox.git", 7 | "box_version": "0.0.1", 8 | "beet_version": "master", 9 | "hostname": "beetbox.local", 10 | "ssh_user": "vagrant", 11 | "ssh_pass": "vagrant" 12 | }, 13 | "builders": [ 14 | { 15 | "type": "virtualbox-iso", 16 | "boot_command": [ 17 | "", 18 | "", 19 | "", 20 | "", 21 | "/install/vmlinuz", 22 | " auto", 23 | " console-setup/ask_detect=false", 24 | " console-setup/layoutcode=us", 25 | " console-setup/modelcode=pc105", 26 | " debconf/frontend=noninteractive", 27 | " debian-installer=en_US", 28 | " fb=false", 29 | " initrd=/install/initrd.gz", 30 | " kbd-chooser/method=us", 31 | " keyboard-configuration/layout=USA", 32 | " keyboard-configuration/variant=USA", 33 | " locale=en_US", 34 | " netcfg/get_domain=vm", 35 | " netcfg/get_hostname=vagrant", 36 | " grub-installer/bootdev=/dev/sda", 37 | " noapic", 38 | " preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/preseed.cfg", 39 | " -- ", 40 | "" 41 | ], 42 | "boot_wait": "10s", 43 | "disk_size": 81920, 44 | "guest_os_type": "Ubuntu_64", 45 | "hard_drive_interface": "sata", 46 | "http_directory": "packer/http", 47 | "iso_checksum": "0a03608988cfd2e50567990dc8be96fb3c501e198e2e6efcb846d89efc7b89f2", 48 | "iso_checksum_type": "sha256", 49 | "iso_url": "http://releases.ubuntu.com/16.04/ubuntu-16.04.4-server-amd64.iso", 50 | "output_directory": "output-{{ user `cloud_build_name` }}-virtualbox-iso", 51 | "ssh_username": "{{ user `ssh_user` }}", 52 | "ssh_password": "{{ user `ssh_pass` }}", 53 | "ssh_port": 22, 54 | "ssh_wait_timeout": "10000s", 55 | "shutdown_command": "echo '{{ user `ssh_pass` }}'|sudo -S shutdown -P now", 56 | "guest_additions_url": "http://download.virtualbox.org/virtualbox/5.1.28/VBoxGuestAdditions_5.1.28.iso", 57 | "guest_additions_sha256": "66824ee3a0373da62b15f6687a68e2305d7e62d700e538cf32705227bb38c46d", 58 | "guest_additions_path": "VBoxGuestAdditions_{{ .Version }}.iso", 59 | "virtualbox_version_file": ".vbox_version", 60 | "vm_name": "beetbox_{{ user `box_version` }}", 61 | "vboxmanage": [ 62 | [ 63 | "modifyvm", 64 | "{{.Name}}", 65 | "--memory", 66 | "1024" 67 | ], 68 | [ 69 | "modifyvm", 70 | "{{.Name}}", 71 | "--cpus", 72 | "1" 73 | ] 74 | ] 75 | } 76 | ], 77 | "provisioners": [ 78 | { 79 | "environment_vars": [ 80 | "BEET_REPO={{ user `beet_repo` }}", 81 | "BEET_VERSION={{ user `beet_version` }}" 82 | ], 83 | "type": "shell", 84 | "scripts": [ 85 | "beetbox.sh" 86 | ], 87 | "execute_command": "{{ .Vars }} bash '{{ .Path }}'" 88 | }, 89 | { 90 | "type": "shell", 91 | "scripts": [ 92 | "packer/scripts/minimize.sh", 93 | "packer/scripts/cleanup.sh" 94 | ], 95 | "execute_command": "sudo -E bash '{{ .Path }}'" 96 | } 97 | ], 98 | "post-processors": [ 99 | [ 100 | { 101 | "type": "vagrant", 102 | "compression_level": 9, 103 | "output": "{{ user `cloud_username` }}-{{ user `cloud_build_name` }}-{{ .Provider }}.box" 104 | }, 105 | { 106 | "type": "vagrant-cloud", 107 | "box_tag": "{{ user `cloud_username` }}/{{ user `cloud_build_name` }}", 108 | "access_token": "{{user `cloud_token`}}", 109 | "version": "{{user `box_version`}}" 110 | } 111 | ] 112 | ] 113 | } 114 | -------------------------------------------------------------------------------- /tests/PluginTest.php: -------------------------------------------------------------------------------- 1 | rootDir = realpath(realpath(__DIR__ . '/..')); 38 | 39 | // Prepare temp directory. 40 | $this->fs = new Filesystem(); 41 | $this->tmpDir = realpath(sys_get_temp_dir()) . DIRECTORY_SEPARATOR . 'beetbox'; 42 | $this->ensureDirectoryExistsAndClear($this->tmpDir); 43 | 44 | $this->writeComposerJSON(); 45 | 46 | chdir($this->tmpDir); 47 | } 48 | 49 | /** 50 | * tearDown 51 | * 52 | * @return void 53 | */ 54 | public function tearDown() 55 | { 56 | $this->fs->removeDirectory($this->tmpDir); 57 | } 58 | 59 | /** 60 | * Tests a composer install and update to ensure Vagrantfile is added. 61 | */ 62 | public function testComposerInstallAndUpdate() { 63 | $vagrantFile = $this->tmpDir . DIRECTORY_SEPARATOR . 'Vagrantfile'; 64 | $this->assertFileNotExists($vagrantFile, 'Vagrantfile should not be exist.'); 65 | $this->composer('install'); 66 | $this->assertFileExists($vagrantFile, 'Vagrantfile should be automatically installed.'); 67 | $this->fs->remove($vagrantFile); 68 | $this->assertFileNotExists($vagrantFile, 'Vagrantfile should not be exist.'); 69 | $this->composer('update'); 70 | $this->assertFileExists($vagrantFile, 'Vagrantfile should be automatically recreated.'); 71 | } 72 | 73 | /** 74 | * Writes the default composer json to the temp direcoty. 75 | */ 76 | protected function writeComposerJSON() { 77 | $json = json_encode($this->composerJSONDefaults(), JSON_PRETTY_PRINT); 78 | // Write composer.json. 79 | file_put_contents($this->tmpDir . '/composer.json', $json); 80 | } 81 | 82 | /** 83 | * Provides the default composer.json data. 84 | * 85 | * @return array 86 | */ 87 | protected function composerJSONDefaults() { 88 | return array( 89 | 'repositories' => array( 90 | array( 91 | 'type' => 'path', 92 | 'url' => $this->rootDir, 93 | ) 94 | ), 95 | 'require' => array( 96 | 'beet/box' => "*" 97 | ), 98 | 'minimum-stability' => 'dev' 99 | ); 100 | } 101 | 102 | /** 103 | * Wrapper for the composer command. 104 | * 105 | * @param string $command 106 | * Composer command name, arguments and/or options 107 | */ 108 | protected function composer($command) { 109 | chdir($this->tmpDir); 110 | passthru(escapeshellcmd($this->rootDir . '/vendor/bin/composer ' . $command), $exit_code); 111 | if ($exit_code !== 0) { 112 | throw new \Exception('Composer returned a non-zero exit code'); 113 | } 114 | } 115 | 116 | /** 117 | * Makes sure the given directory exists and has no content. 118 | * 119 | * @param string $directory 120 | */ 121 | protected function ensureDirectoryExistsAndClear($directory) { 122 | if (is_dir($directory)) { 123 | $this->fs->removeDirectory($directory); 124 | } 125 | mkdir($directory, 0777, true); 126 | } 127 | } 128 | --------------------------------------------------------------------------------