├── machine ├── application │ ├── app-php │ │ ├── .gitignore │ │ ├── public │ │ │ ├── phpinfo.php │ │ │ ├── index.html │ │ │ └── index.php │ │ ├── composer.json │ │ ├── healthcheck.php │ │ └── composer.lock │ └── app-node │ │ ├── .gitignore │ │ ├── package.json │ │ ├── app.js │ │ └── package-lock.json ├── ansible │ ├── roles │ │ ├── server │ │ │ ├── files │ │ │ │ └── cachefilesd │ │ │ ├── templates │ │ │ │ └── timezone.j2 │ │ │ ├── defaults │ │ │ │ └── main.yml │ │ │ ├── handlers │ │ │ │ └── main.yml │ │ │ └── tasks │ │ │ │ ├── cachefilesd.yml │ │ │ │ └── main.yml │ │ ├── xdebug │ │ │ ├── defaults │ │ │ │ └── main.yml │ │ │ └── tasks │ │ │ │ └── main.yml │ │ ├── app-node │ │ │ ├── meta │ │ │ │ └── main.yml │ │ │ ├── tasks │ │ │ │ ├── main.yml │ │ │ │ ├── dependencies.yml │ │ │ │ └── systemd-service.yml │ │ │ ├── handlers │ │ │ │ └── main.yml │ │ │ └── templates │ │ │ │ └── app-node.service.j2 │ │ ├── app-php │ │ │ ├── tasks │ │ │ │ ├── main.yml │ │ │ │ ├── dependencies.yml │ │ │ │ └── nginx-site.yml │ │ │ ├── meta │ │ │ │ └── main.yml │ │ │ ├── handlers │ │ │ │ └── main.yml │ │ │ └── templates │ │ │ │ └── nginx.default.j2 │ │ ├── nginx │ │ │ ├── handlers │ │ │ │ └── main.yml │ │ │ └── tasks │ │ │ │ └── main.yml │ │ ├── redis │ │ │ ├── handlers │ │ │ │ └── main.yml │ │ │ ├── tasks │ │ │ │ ├── setup.yml │ │ │ │ └── main.yml │ │ │ ├── defaults │ │ │ │ └── main.yml │ │ │ └── templates │ │ │ │ └── redis.conf.j2 │ │ ├── composer │ │ │ ├── templates │ │ │ │ └── auth.json.j2 │ │ │ └── tasks │ │ │ │ └── main.yml │ │ ├── mysql │ │ │ ├── handlers │ │ │ │ └── main.yml │ │ │ ├── templates │ │ │ │ └── mysqld.conf.j2 │ │ │ └── tasks │ │ │ │ ├── dump-import.yml │ │ │ │ └── main.yml │ │ ├── mongodb │ │ │ ├── handlers │ │ │ │ └── main.yml │ │ │ ├── templates │ │ │ │ └── mongod.conf.j2 │ │ │ └── tasks │ │ │ │ ├── main.yml │ │ │ │ └── dump-import.yml │ │ ├── nodejs │ │ │ ├── templates │ │ │ │ └── npm.sh.j2 │ │ │ ├── tasks │ │ │ │ ├── yarn.yml │ │ │ │ ├── setup.yml │ │ │ │ └── main.yml │ │ │ └── defaults │ │ │ │ └── main.yml │ │ └── php │ │ │ ├── handlers │ │ │ └── main.yml │ │ │ ├── tasks │ │ │ ├── configure.yml │ │ │ ├── php-cli.yml │ │ │ ├── main.yml │ │ │ └── php-fpm.yml │ │ │ └── defaults │ │ │ └── main.yml │ ├── inventory │ │ ├── hosts │ │ └── ansible.cfg │ ├── vars │ │ ├── locals.yml.dist │ │ └── globals.yml │ ├── playbook.yml │ └── files │ │ ├── authorized_keys │ │ └── ansible.sh └── dump │ ├── mongodb │ ├── example_collection_1.json │ └── example_collection_2.json │ └── mysql.sql ├── .gitignore ├── .editorconfig ├── Vagrantfile └── README.md /machine/application/app-php/.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | -------------------------------------------------------------------------------- /machine/ansible/roles/server/files/cachefilesd: -------------------------------------------------------------------------------- 1 | RUN=yes 2 | -------------------------------------------------------------------------------- /machine/application/app-node/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /machine/ansible/inventory/hosts: -------------------------------------------------------------------------------- 1 | [vagrant] 2 | 10.10.10.10 3 | -------------------------------------------------------------------------------- /machine/application/app-php/public/phpinfo.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Phanbox Static HTML 6 | 7 | 8 | It works! 9 |

Phanbox Static HTML

10 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /machine/ansible/roles/php/tasks/php-cli.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Ensure timezone is set in cli php.ini 3 | lineinfile: dest=/etc/php/7.1/cli/php.ini 4 | regexp='date.timezone =' 5 | line='date.timezone = {{ php_timezone }}' 6 | 7 | - name: disabling opcache cli 8 | lineinfile: dest=/etc/php/7.1/cli/php.ini 9 | regexp='opcache.enable_cli=' 10 | line='opcache.enable_cli=0' 11 | -------------------------------------------------------------------------------- /machine/ansible/roles/server/tasks/cachefilesd.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install Cachefilesd Packages 3 | become: true 4 | apt: pkg=cachefilesd state=latest 5 | 6 | - name: Enable Cachefilesd 7 | become: true 8 | copy: src=cachefilesd dest=/etc/default/cachefilesd mode=0755 9 | notify: restart cachefilesd 10 | 11 | - name: Insure Cachefilesd is running correctly 12 | systemd: name=cachefilesd state=started enabled=yes 13 | -------------------------------------------------------------------------------- /machine/ansible/files/authorized_keys: -------------------------------------------------------------------------------- 1 | ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key 2 | -------------------------------------------------------------------------------- /machine/application/app-node/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "phanbox-app-node", 3 | "version": "1.0.0", 4 | "description": "Phanbox node appliation", 5 | "author": "Nickolay U. Kofanov", 6 | "private": true, 7 | "scripts": { 8 | "start": "node app.js" 9 | }, 10 | "dependencies": { 11 | "bluebird": "^3.5.0", 12 | "moment": "^2.18.1", 13 | "mongodb": "^2.2.29", 14 | "mysql": "^2.13.0", 15 | "redis": "^2.7.1" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /machine/dump/mysql.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE IF NOT EXISTS `phanbox_example` 2 | ( 3 | `id` INT UNSIGNED AUTO_INCREMENT NOT NULL, 4 | 5 | `what` VARCHAR(100) NOT NULL, 6 | `when` DATETIME NOT NULL, 7 | `where` VARCHAR(100) NULL DEFAULT NULL, 8 | 9 | PRIMARY KEY(`id`) 10 | ); 11 | 12 | INSERT INTO `phanbox_example`(`what`, `when`, `where`) VALUES 13 | ('The dump has been imported', NOW(), CONCAT(@@version_comment, ' - ', @@version)), 14 | ('You may remove this table - it is just an example one', NOW(), NULL); 15 | -------------------------------------------------------------------------------- /machine/ansible/roles/xdebug/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install xDebug 3 | become: true 4 | apt: pkg=php-xdebug state=latest 5 | 6 | - name: Set xDebug parameters 7 | lineinfile: 8 | dest: /etc/php/7.1/mods-available/xdebug.ini 9 | regexp: "{{ item.regexp }}" 10 | line: "{{ item.line }}" 11 | with_items: 12 | - { regexp: "^xdebug.remote_enable", line: "xdebug.remote_enable=on" } 13 | - { regexp: "^xdebug.remote_connect_back", line: "xdebug.remote_connect_back=on" } 14 | - { regexp: "^xdebug.idekey", line: "xdebug.idekey={{ xdebug.idekey }}" } 15 | -------------------------------------------------------------------------------- /machine/application/app-php/public/index.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | <?= $title = 'Phanbox PHP App' ?> 7 | 8 | 9 | It works! 10 | 11 |

12 |

toDayDateTimeString() ?>

13 | 14 |

Environment:

15 |

MySQL connection established

16 |

Redis connection established

17 |

Mongo connection established

18 | 19 | 20 | -------------------------------------------------------------------------------- /machine/ansible/roles/php/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - shell: dpkg-query -W 'php7.1' 3 | ignore_errors: true 4 | register: is_php_installed 5 | 6 | - name: Remove all existing PHP packages 7 | become: true 8 | apt: pkg=php7* autoremove=yes purge=yes state=absent force=yes 9 | when: is_php_installed|failed 10 | 11 | - name: Add repository for Ubuntu 12 | become: true 13 | apt_repository: repo={{ php_ppa }} 14 | 15 | - name: Update apt 16 | become: true 17 | apt: update_cache=yes 18 | 19 | - name: Install PHP Packages 20 | become: true 21 | apt: pkg={{ item }} state=latest 22 | with_items: "{{ php_packages }}" 23 | when: php_packages is defined 24 | notify: 25 | - restart php7-fpm 26 | - restart nginx 27 | 28 | - include: configure.yml 29 | -------------------------------------------------------------------------------- /machine/ansible/roles/app-node/templates/app-node.service.j2: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | [Unit] 3 | Description=node application 4 | RequiresMountsFor=/vagrant 5 | After=nginx.service 6 | After=mysql.service 7 | 8 | [Service] 9 | Environment=NODE_PORT={{ app_node.port }} NODE_ENV={{ app_node.env | default('development') }} LOG_FILE=/var/log/{{ app_node.service_name }}.log 10 | Type=simple 11 | 12 | User=vagrant 13 | Group=vagrant 14 | PermissionsStartOnly=true 15 | 16 | ExecStartPre=/usr/bin/touch ${LOG_FILE} 17 | ExecStartPre=/bin/chmod 0666 ${LOG_FILE} 18 | 19 | ExecStart=/bin/sh -c 'cd {{ app_node.root }} && npm start >> ${LOG_FILE} 2>&1' 20 | 21 | WorkingDirectory={{ app_node.root }} 22 | Restart=on-failure 23 | RestartSec=10 24 | 25 | [Install] 26 | WantedBy=multi-user.target 27 | -------------------------------------------------------------------------------- /machine/ansible/roles/nodejs/tasks/yarn.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Add Yarn GPG key 3 | become: true 4 | apt_key: 5 | url: https://dl.yarnpkg.com/debian/pubkey.gpg 6 | state: present 7 | 8 | - name: Ensure Yarn sources list file exists 9 | become: true 10 | file: 11 | path: /etc/apt/sources.list.d/yarn.list 12 | owner: root 13 | mode: 0644 14 | state: touch 15 | 16 | - name: Ensure Yarn package is in sources list 17 | become: true 18 | lineinfile: 19 | dest: /etc/apt/sources.list.d/yarn.list 20 | regexp: 'deb http://dl.yarnpkg.com/debian/ stable main' 21 | line: 'deb http://dl.yarnpkg.com/debian/ stable main' 22 | state: present 23 | 24 | - name: Update APT cache 25 | become: true 26 | apt: update_cache=yes 27 | 28 | - name: Yarn Install 29 | become: true 30 | package: name=yarn state=latest 31 | -------------------------------------------------------------------------------- /machine/ansible/roles/mongodb/templates/mongod.conf.j2: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | # 3 | # mongod.conf 4 | 5 | # for documentation of all options, see: 6 | # http://docs.mongodb.org/manual/reference/configuration-options/ 7 | 8 | # Where and how to store data. 9 | storage: 10 | dbPath: /var/lib/mongodb 11 | journal: 12 | enabled: true 13 | # engine: 14 | # mmapv1: 15 | # wiredTiger: 16 | 17 | # where to write logging data. 18 | systemLog: 19 | destination: file 20 | logAppend: true 21 | path: /var/log/mongodb/mongod.log 22 | 23 | # network interfaces 24 | net: 25 | port: 27017 26 | bindIp: 0.0.0.0 27 | 28 | #processManagement: 29 | 30 | security: 31 | authorization: "enabled" 32 | 33 | #operationProfiling: 34 | 35 | #replication: 36 | 37 | #sharding: 38 | 39 | ## Enterprise-Only Options: 40 | 41 | #auditLog: 42 | 43 | #snmp: 44 | -------------------------------------------------------------------------------- /machine/ansible/roles/composer/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: Install Composer 2 | shell: curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer creates=/usr/local/bin/composer 3 | 4 | - name: Assures /home/vagrant/.composer directory exists 5 | file: path=/home/vagrant/.composer state=directory 6 | 7 | - name: Create composer config directory 8 | file: path=/home/vagrant/.composer state=directory owner=vagrant group=vagrant mode=0755 9 | 10 | - name: Configure composer GitHub token 11 | become: true 12 | become_user: vagrant 13 | template: src=auth.json.j2 dest=/home/vagrant/.composer/auth.json 14 | when: composer.github_token is defined 15 | 16 | - name: Install php-cs-fixer 17 | shell: wget http://cs.sensiolabs.org/download/php-cs-fixer-v2.phar -O php-cs-fixer && chmod a+x php-cs-fixer && mv php-cs-fixer /usr/local/bin/php-cs-fixer 18 | args: 19 | creates: /usr/local/bin/php-cs-fixer 20 | -------------------------------------------------------------------------------- /machine/ansible/vars/globals.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Override defaults for php application 3 | app_php: 4 | env: development # Available as getenv('APP_ENV') in PHP app 5 | root: /vagrant/application/app-php 6 | document_root: /vagrant/application/app-php/public 7 | server_name: phanbox.local 8 | 9 | # Override defaults for node application 10 | app_node: 11 | env: development # Available as process.env['NODE_ENV'] in Node.js app 12 | root: /vagrant/application/app-node 13 | port: 3000 14 | service_name: app-node 15 | 16 | # MySQL configurations 17 | mysql: 18 | database: app 19 | user: app 20 | password: app 21 | root_password: password # You won't be able to change it after first provisioning 22 | dump_file: /vagrant/dump/mysql 23 | 24 | # MongoDB configurations 25 | mongodb: 26 | database: app 27 | user: app 28 | password: app 29 | root_password: password 30 | dump_directory: /vagrant/dump/mongodb 31 | dump_array_mode: true 32 | -------------------------------------------------------------------------------- /machine/ansible/roles/php/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | php_ppa: "ppa:ondrej/php" 3 | php_packages: 4 | - php7.1-fpm 5 | - php7.1-cli 6 | - php7.1-common 7 | - php7.1-json 8 | - php7.1-opcache 9 | - php7.1-mysql 10 | - php7.1-phpdbg 11 | - php7.1-mbstring 12 | - php7.1-gd 13 | - php7.1-imap 14 | - php7.1-ldap 15 | - php7.1-dev 16 | - php7.1-intl 17 | - php7.1-gd 18 | - php7.1-curl 19 | - php7.1-zip 20 | - php7.1-xml 21 | - php-redis 22 | - php-mongodb 23 | - php-ast 24 | php_timezone: UTC 25 | php_upload_max_filesize: "128M" 26 | php_post_max_size: "128M" 27 | php_memory_limit: "1024M" 28 | php_max_execution_time: 180 29 | 30 | php_opcache_enable: 1 31 | php_opcache_revalidate_freq: 0 32 | php_opcache_opcache_validate_timestamps: 1 33 | php_opcache_max_accelerated_files: 20000 34 | php_opcache_memory_consumption: 192 35 | php_opcache_interned_strings_buffer: 16 36 | php_opcache_fast_shutdown: 1 37 | 38 | php_allow_url_fopen: 0 39 | -------------------------------------------------------------------------------- /machine/application/app-php/healthcheck.php: -------------------------------------------------------------------------------- 1 | query('SELECT 1'); 11 | 12 | $mysqlConnected = true; 13 | } catch (Throwable $e) { 14 | // Suppress exception 15 | } 16 | 17 | try { 18 | $redis = new Redis(); 19 | $redis->connect('127.0.0.1'); 20 | $redis->ping(); 21 | 22 | $redisConnected = true; 23 | } catch (Throwable $e) { 24 | // Suppress exception 25 | } 26 | 27 | try { 28 | $mongo = new MongoDB\Client('mongodb://app:app@127.0.0.1/app'); 29 | $appDb = $mongo->app; 30 | $cursor = $appDb->command(['ping' => 1]); 31 | 32 | assert($cursor->toArray()[0]['ok'] === 1); 33 | 34 | $mongoConnected = true; 35 | } catch (Throwable $e) { 36 | // Suppress exception 37 | } 38 | 39 | -------------------------------------------------------------------------------- /machine/ansible/files/ansible.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | INSTALLED=$(dpkg -l | grep ansible) 4 | 5 | if [ "$INSTALLED" != "" ]; then 6 | echo "Package ansible has been already installed" 7 | else 8 | echo "Installing ansible package...." 9 | # Update Repositories 10 | sudo apt-get update 11 | 12 | # Add Ansible Repository & Install Ansible 13 | sudo apt-get install -y software-properties-common 14 | sudo add-apt-repository -y ppa:ansible/ansible 15 | sudo apt-get update 16 | sudo apt-get install -y ansible 17 | 18 | # Setup Ansible for Local Use and Run 19 | cp /vagrant/ansible/inventory/hosts /etc/ansible/hosts -f 20 | cp /vagrant/ansible/inventory/ansible.cfg /etc/ansible/ansible.cfg -f 21 | chmod 666 /etc/ansible/hosts 22 | chmod 666 /etc/ansible/ansible.cfg 23 | cat /vagrant/ansible/files/authorized_keys >> /home/vagrant/.ssh/authorized_keys 24 | fi 25 | 26 | sudo ansible-playbook /vagrant/ansible/playbook.yml --connection="local" 27 | -------------------------------------------------------------------------------- /machine/ansible/roles/nodejs/tasks/setup.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Ensure apt-transport-https is installed. 3 | apt: name=apt-transport-https state=present 4 | 5 | - name: Add Nodesource apt key. 6 | apt_key: 7 | url: https://keyserver.ubuntu.com/pks/lookup?op=get&fingerprint=on&search=0x1655A0AB68576280 8 | id: "68576280" 9 | state: present 10 | 11 | - name: Add NodeSource repositories for Node.js. 12 | apt_repository: 13 | repo: "{{ item }}" 14 | state: present 15 | with_items: 16 | - "deb https://deb.nodesource.com/node_{{ nodejs_version }} {{ ansible_distribution_release }} main" 17 | - "deb-src https://deb.nodesource.com/node_{{ nodejs_version }} {{ ansible_distribution_release }} main" 18 | register: node_repo 19 | 20 | - name: Update apt cache if repo was added. 21 | apt: update_cache=yes 22 | when: node_repo.changed 23 | 24 | - name: Ensure Node.js and npm are installed. 25 | apt: "name=nodejs={{ nodejs_version|regex_replace('x', '') }}* state=present" 26 | -------------------------------------------------------------------------------- /machine/ansible/roles/mysql/templates/mysqld.conf.j2: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | # 3 | # The Percona Server 5.7 configuration file. 4 | # 5 | # One can use all long options that the program supports. 6 | # Run program with --help to get a list of available options and with 7 | # --print-defaults to see which it would actually understand and use. 8 | # 9 | # For explanations see 10 | # http://dev.mysql.com/doc/mysql/en/server-system-variables.html 11 | 12 | [mysqld] 13 | user = mysql 14 | pid-file = /var/run/mysqld/mysqld.pid 15 | socket = /var/run/mysqld/mysqld.sock 16 | port = 3306 17 | bind-address = 0.0.0.0 18 | basedir = /usr 19 | datadir = /var/lib/mysql 20 | tmpdir = /tmp 21 | lc-messages-dir = /usr/share/mysql 22 | explicit_defaults_for_timestamp 23 | 24 | log-error = /var/log/mysql/error.log 25 | 26 | # Recommended in standard MySQL setup 27 | sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_ALL_TABLES 28 | 29 | # Disabling symbolic-links is recommended to prevent assorted security risks 30 | symbolic-links=0 31 | -------------------------------------------------------------------------------- /machine/ansible/roles/nodejs/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Set the version of Node.js to install ("0.10", "0.12", "4.x", "5.x", "6.x"). 3 | # Version numbers from Nodesource: https://github.com/nodesource/distributions 4 | nodejs_version: "8.x" 5 | 6 | # The user for whom the npm packages will be installed. 7 | nodejs_install_npm_user: vagrant 8 | 9 | # The directory for global installations. 10 | npm_config_prefix: "/usr/local/lib/npm" 11 | 12 | # Set to true to suppress the UID/GID switching when running package scripts. If set explicitly to false, then installing as a non-root user will fail. 13 | npm_config_unsafe_perm: "true" 14 | 15 | # Define a list of global packages to be installed with NPM. 16 | # nodejs_npm_global_packages: 17 | # # Install a specific version of a package. 18 | # - name: jslint 19 | # version: 0.9.3 20 | # # Install the latest stable release of a package. 21 | # - name: node-sass 22 | # # This shorthand syntax also works (same as previous example). 23 | # - node-sass 24 | nodejs_npm_global_packages: 25 | - name: gulp 26 | - name: grunt 27 | - name: nodemon 28 | -------------------------------------------------------------------------------- /machine/ansible/roles/nodejs/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - include: setup.yml 3 | 4 | - name: Define nodejs_install_npm_user 5 | set_fact: 6 | nodejs_install_npm_user: "{{ ansible_user | default(lookup('env', 'USER')) }}" 7 | when: nodejs_install_npm_user is not defined 8 | 9 | - name: Create npm global directory 10 | file: 11 | path: "{{ npm_config_prefix }}" 12 | owner: "{{ nodejs_install_npm_user }}" 13 | group: "{{ nodejs_install_npm_user }}" 14 | state: directory 15 | 16 | - name: Add npm_config_prefix bin directory to global $PATH. 17 | template: 18 | src: npm.sh.j2 19 | dest: /etc/profile.d/npm.sh 20 | mode: 0644 21 | 22 | - name: Ensure npm global packages are installed. 23 | become: true 24 | become_user: "{{ nodejs_install_npm_user }}" 25 | npm: 26 | name: "{{ item.name | default(item) }}" 27 | version: "{{ item.version | default('latest') }}" 28 | global: yes 29 | state: latest 30 | environment: 31 | NPM_CONFIG_PREFIX: "{{ npm_config_prefix }}" 32 | NODE_PATH: "{{ npm_config_prefix }}/lib/node_modules" 33 | NPM_CONFIG_UNSAFE_PERM: "{{ npm_config_unsafe_perm }}" 34 | with_items: "{{ nodejs_npm_global_packages }}" 35 | 36 | - include: yarn.yml 37 | -------------------------------------------------------------------------------- /machine/ansible/roles/mysql/tasks/dump-import.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: MySQL | Create databases 3 | mysql_db: name={{ mysql.database }} state=present login_user=root login_password={{ mysql.root_password }} 4 | register: db_created 5 | 6 | - block: 7 | - name: MySQL | Check dump file existence 8 | stat: path={{ mysql.dump_file }} 9 | register: dump_file 10 | - name: MySQL | Import dump 11 | mysql_db: name={{ mysql.database }} state=import login_user=root login_password={{ mysql.root_password }} target={{ mysql.dump_file }} 12 | when: 13 | - db_created.changed 14 | - dump_file.stat.exists and not(dump_file.stat.isdir) 15 | when: not((mysql.dump_file is undefined) or (mysql.dump_file is none) or (mysql.dump_file|trim == '')) 16 | 17 | - name: MySQL | Ensure anonymous users are not in the database 18 | mysql_user: name='' host={{ item }} state=absent login_user=root login_password={{ mysql.root_password }} 19 | with_items: 20 | - localhost 21 | - "{{ current_hostname.stdout | lower }}" 22 | 23 | - name: MySQL | Create application user 24 | mysql_user: name={{ mysql.user }} password={{ mysql.password }} priv={{ mysql.database }}.*:ALL state=present login_user=root login_password={{ mysql.root_password }} 25 | -------------------------------------------------------------------------------- /machine/ansible/roles/redis/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | redis_package: redis-server 3 | redis_daemon: redis-server 4 | redis_conf_path: /etc/redis/redis.conf 5 | 6 | redis_port: 6379 7 | redis_bind_interface: 0.0.0.0 8 | redis_unixsocket: '' 9 | redis_timeout: 300 10 | 11 | redis_loglevel: "notice" 12 | redis_logfile: /var/log/redis/redis-server.log 13 | 14 | redis_databases: 16 15 | 16 | # Set to an empty set to disable persistence (saving the DB to disk). 17 | redis_save: 18 | - 900 1 19 | - 300 10 20 | - 60 10000 21 | 22 | redis_rdbcompression: "yes" 23 | redis_dbfilename: dump.rdb 24 | redis_dbdir: /var/lib/redis 25 | 26 | redis_maxmemory: 0 27 | redis_maxmemory_policy: "noeviction" 28 | redis_maxmemory_samples: 5 29 | 30 | redis_appendonly: "no" 31 | redis_appendfsync: "everysec" 32 | 33 | # Add extra include files for local configuration/overrides. 34 | redis_includes: [] 35 | 36 | # Require authentication to Redis with a password. 37 | redis_requirepass: "" 38 | 39 | # Disable certain Redis commands for security reasons. 40 | redis_disabled_commands: [] 41 | # - FLUSHDB 42 | # - FLUSHALL 43 | # - KEYS 44 | # - PEXPIRE 45 | # - DEL 46 | # - CONFIG 47 | # - SHUTDOWN 48 | # - BGREWRITEAOF 49 | # - BGSAVE 50 | # - SAVE 51 | # - SPOP 52 | # - SREM 53 | # - RENAME 54 | # - DEBUG 55 | -------------------------------------------------------------------------------- /machine/ansible/roles/app-php/templates/nginx.default.j2: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | server { 3 | listen 80; 4 | charset utf-8; 5 | server_name {{ app_php.server_name }} www.{{ app_php.server_name }}; 6 | index index.html index.htm index.php; 7 | client_max_body_size 500m; 8 | 9 | access_log /var/log/nginx/{{ app_php.server_name }}.access.log; 10 | error_log /var/log/nginx/{{ app_php.server_name }}.error.log; 11 | 12 | location / { 13 | client_max_body_size 200m; 14 | 15 | if (!-f $request_filename) { 16 | rewrite ^(.*)$ /index.php?q=$1 last; 17 | break; 18 | } 19 | 20 | root {{ app_php.document_root }}; 21 | try_files $uri $uri/ index.php /index.php$is_args$args; 22 | } 23 | 24 | location ~ \.php$ { 25 | root {{ app_php.document_root }}; 26 | index index.html index.htm index.php; 27 | fastcgi_index index.php; 28 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 29 | fastcgi_param APP_ENV dev; 30 | fastcgi_param APPLICATION_ENV development; 31 | fastcgi_pass unix:/run/php/php7.1-fpm.sock; 32 | fastcgi_read_timeout 300; 33 | fastcgi_split_path_info ^(.+\.php)(/.*)$; 34 | fastcgi_param APP_ENV "{{ app_node.env | default('development') }}"; 35 | include fastcgi_params; 36 | } 37 | 38 | sendfile off; 39 | } 40 | -------------------------------------------------------------------------------- /machine/ansible/roles/server/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Update apt 3 | become: true 4 | apt: update_cache=yes 5 | 6 | - name: Make sure aptitude is installed 7 | become: true 8 | apt: pkg=aptitude state=latest 9 | 10 | - name: Update all packages to the latest version 11 | become: true 12 | apt: upgrade=yes 13 | 14 | - name: Install System Packages 15 | become: true 16 | apt: pkg={{ item }} state=latest 17 | with_items: "{{ server_packages }}" 18 | when: server_packages is defined 19 | 20 | - name: Configure the timezone 21 | become: true 22 | template: src=timezone.j2 dest=/etc/timezone 23 | 24 | - name: More Configure the timezone 25 | become: true 26 | file: src=/usr/share/zoneinfo/{{server_timezone}} dest=/etc/localtime state=link force=yes backup=yes 27 | 28 | - name: Set default system language pack 29 | shell: locale-gen {{ server_locale }} 30 | become: true 31 | 32 | - name: Set default system language vars 33 | become: true 34 | lineinfile: 35 | dest: /etc/default/locale 36 | regexp: "{{ item.regexp }}" 37 | line: "{{ item.line }}" 38 | with_items: 39 | - { regexp: "^LANG\b", line: "LANG={{ server_locale }}" } 40 | - { regexp: "^LANGUAGE\b", line: "LANGUAGE={{ server_locale }}" } 41 | - { regexp: "^LC_ALL\b", line: "LC_ALL={{ server_locale }}" } 42 | 43 | - name: Set default GIT editor 44 | shell: git config --global core.editor vim 45 | 46 | - include: cachefilesd.yml 47 | -------------------------------------------------------------------------------- /machine/ansible/roles/redis/templates/redis.conf.j2: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | 3 | daemonize yes 4 | pidfile /var/run/redis/{{ redis_daemon }}.pid 5 | port {{ redis_port }} 6 | bind {{ redis_bind_interface }} 7 | 8 | {% if redis_unixsocket %} 9 | unixsocket {{ redis_unixsocket }} 10 | {% endif %} 11 | 12 | timeout {{ redis_timeout }} 13 | 14 | loglevel {{ redis_loglevel }} 15 | logfile {{ redis_logfile }} 16 | 17 | # To enable logging to the system logger, just set 'syslog-enabled' to yes, 18 | # and optionally update the other syslog parameters to suit your needs. 19 | # syslog-enabled no 20 | # syslog-ident redis 21 | # syslog-facility local0 22 | 23 | databases {{ redis_databases }} 24 | 25 | {% for save in redis_save %} 26 | save {{ save }} 27 | {% endfor %} 28 | 29 | rdbcompression {{ redis_rdbcompression }} 30 | dbfilename {{ redis_dbfilename }} 31 | dir {{ redis_dbdir }} 32 | 33 | # maxclients 128 34 | 35 | {% if redis_maxmemory %} 36 | maxmemory {{ redis_maxmemory }} 37 | maxmemory-policy {{ redis_maxmemory_policy }} 38 | maxmemory-samples {{ redis_maxmemory_samples }} 39 | {% endif %} 40 | 41 | appendonly {{ redis_appendonly }} 42 | appendfsync {{ redis_appendfsync }} 43 | no-appendfsync-on-rewrite no 44 | 45 | {% for include in redis_includes %} 46 | include {{ include }} 47 | {% endfor %} 48 | 49 | {% if redis_requirepass %} 50 | requirepass {{ redis_requirepass }} 51 | {% endif %} 52 | 53 | {% for redis_disabled_command in redis_disabled_commands %} 54 | rename-command {{ redis_disabled_command }} "" 55 | {% endfor %} 56 | -------------------------------------------------------------------------------- /machine/ansible/roles/mongodb/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: MongoDB | Fetch MongoDB signing key 3 | become: true 4 | command: apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 0C49F3730359A14518585931BC711F9BA15703C6 5 | 6 | - name: MongoDB | Add MongoDB repository 7 | become: true 8 | shell: 9 | echo "deb [ arch=amd64,arm64 ] http://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.4 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-3.4.list 10 | creates=/etc/apt/sources.list.d/mongodb-org-3.4.list 11 | 12 | - name: MongoDB | Install latest MongoDB release 13 | apt: pkg=mongodb-org state=present update_cache=yes 14 | 15 | - name: MongoDB | Insure daemon is running correctly 16 | systemd: name=mongod state=started enabled=yes 17 | 18 | - name: MongoDB | Install python package (required for ansible) 19 | become: true 20 | apt: pkg=python-pymongo state=present 21 | 22 | - name: MongoDB | Persist root password 23 | become: true 24 | copy: 25 | content: "" 26 | dest: /root/.mongodb_root_created 27 | mode: 0555 28 | register: mongodb_root_created 29 | 30 | - name: MongoDB | Add root user 31 | mongodb_user: 32 | database: admin 33 | name: root 34 | password: "{{ mongodb.root_password }}" 35 | roles: readWriteAnyDatabase,userAdminAnyDatabase,dbAdminAnyDatabase,root 36 | state: present 37 | update_password: on_create 38 | when: mongodb_root_created.changed 39 | 40 | - name: MongoDB | Create default configuration template 41 | template: src=mongod.conf.j2 dest=/etc/mongod.conf owner=root group=root mode=0644 42 | notify: mongodb restart 43 | 44 | - include: dump-import.yml 45 | -------------------------------------------------------------------------------- /machine/ansible/roles/mongodb/tasks/dump-import.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: MongoDB | Add application user 3 | mongodb_user: 4 | login_user: root 5 | login_password: "{{ mongodb.root_password }}" 6 | database: "{{ mongodb.database }}" 7 | name: "{{ mongodb.user }}" 8 | password: "{{ mongodb.password }}" 9 | roles: readWrite,dbAdmin,userAdmin 10 | state: present 11 | 12 | - name: MongoDB | Add application reader user 13 | mongodb_user: 14 | login_user: root 15 | login_password: "{{ mongodb.root_password }}" 16 | database: "{{ mongodb.database }}" 17 | name: "{{ mongodb.database }}_reader" 18 | password: "{{ mongodb.database }}_reader" 19 | roles: read 20 | state: present 21 | update_password: on_create 22 | register: reader_created 23 | 24 | - block: 25 | - name: MongoDB | Check dump directory existence 26 | stat: path={{ mongodb.dump_directory }} 27 | register: dump_directory 28 | - name: MongoDB | Import dump 29 | shell: | 30 | ls -1 {{ mongodb.dump_directory }}/*.json | sed 's/.json$//' | while read FILENAME; do 31 | COLLECTION=$(basename $FILENAME) 32 | mongoimport \ 33 | --username {{ mongodb.user }} \ 34 | --password {{ mongodb.password }} \ 35 | --db {{ mongodb.database }} \ 36 | {{ ((mongodb.dump_array_mode is defined) and mongodb.dump_array_mode) | ternary('--jsonArray', '') }} \ 37 | --collection $COLLECTION --file $FILENAME.json 38 | done 39 | exit 0 40 | when: 41 | - reader_created.changed 42 | - dump_directory.stat.exists and dump_directory.stat.isdir 43 | when: not((mongodb.dump_directory is undefined) or (mongodb.dump_directory is none) or (mongodb.dump_directory|trim == '')) 44 | -------------------------------------------------------------------------------- /machine/ansible/roles/mysql/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Retrieve the current hostname, because {{ ansible_hostname }} still contains the old name 3 | - shell: hostname 4 | register: current_hostname 5 | 6 | - name: Add Percona apt signing key 7 | become: true 8 | apt_key: keyserver=keys.gnupg.net id=8507EFA5 state=present 9 | 10 | - name: Add Percona repository 11 | become: true 12 | apt_repository: repo='deb http://repo.percona.com/apt xenial main' state=present 13 | 14 | - name: Add Percona source repository 15 | become: true 16 | apt_repository: repo='deb-src http://repo.percona.com/apt xenial main' state=present 17 | 18 | - name: Update apt cache 19 | become: true 20 | apt: update_cache=true 21 | 22 | - name: Install python packages (required for ansible) 23 | become: true 24 | apt: pkg={{ item }} state=present 25 | with_items: 26 | - vim 27 | - python-pycurl 28 | - python-mysqldb 29 | 30 | - name: Install Percona packages 31 | become: true 32 | apt: pkg={{ item }} state=present update_cache=true 33 | with_items: 34 | - percona-server-common-5.7 35 | - percona-server-client-5.7 36 | - percona-server-server-5.7 37 | environment: 38 | DEBIAN_FRONTEND: noninteractive 39 | 40 | - name: MySQL | Insure daemon is running correctly 41 | systemd: name=mysql state=started enabled=yes 42 | 43 | - name: MySQL | Update root password for all root accounts 44 | mysql_user: name=root host={{ item }} check_implicit_admin=yes password={{ mysql.root_password }} login_user=root login_password={{ mysql.root_password }} 45 | with_items: 46 | - "{{ current_hostname.stdout | lower }}" 47 | - 127.0.0.1 48 | - ::1 49 | - localhost 50 | 51 | - name: MySQL | Create default configuration template 52 | template: src=mysqld.conf.j2 dest=/etc/mysql/percona-server.conf.d/mysqld.cnf owner=root group=root mode=0644 53 | notify: mysql restart 54 | 55 | - include: dump-import.yml 56 | -------------------------------------------------------------------------------- /machine/application/app-node/app.js: -------------------------------------------------------------------------------- 1 | const Promise = require('bluebird'); 2 | 3 | const http = require('http'); 4 | const mysql = require('mysql'); 5 | const redis = require("redis"); 6 | const mongo = require("mongodb"); 7 | const moment = require('moment'); 8 | 9 | const ENV = process.env['NODE_ENV'] || 'unknown'; 10 | const PORT = process.env['NODE_PORT'] || 3000; 11 | 12 | const server = http.createServer((request, response) => { 13 | response.setHeader('Content-Type', 'text/html; charset=utf-8'); 14 | 15 | const mySqlClient = Promise.promisifyAll(mysql.createConnection({ 16 | host: '127.0.0.1', 17 | user: 'app', 18 | password: 'app', 19 | database: 'app', 20 | })); 21 | 22 | const redisClient = Promise.promisifyAll(redis.createClient({ 23 | host: '127.0.0.1', 24 | })); 25 | 26 | const mongoClient = mongo.MongoClient; 27 | let mongoDb = null; 28 | 29 | // Check MySQL 30 | mySqlClient.queryAsync('SELECT 1') 31 | // Check Redis 32 | .then(() => redisClient.pingAsync()) 33 | // Check Mongo 34 | .then(() => mongoClient.connect('mongodb://app:app@127.0.0.1:27017/app')) 35 | .then(db => (mongoDb = db).executeDbAdminCommand({ping: 1})) 36 | // Render Success page when all health checks passed 37 | .then(() => { 38 | const title = 'Phanbox Node.js App'; 39 | const time = moment().format('MMMM Do YYYY, h:mm:ss a'); 40 | 41 | response.writeHead(200); 42 | response.write(` 43 | 44 | 45 | 46 | 47 | ${title} 48 | 49 | 50 | It works! 51 |

${title}

52 |

${time}

53 |

Environment: ${ENV}

54 |

MySQL connection established

55 |

Redis connection established

56 |

Mongo connection established

57 | 58 | 59 | `); 60 | }) 61 | .catch(err => { 62 | response.writeHead(500); 63 | response.write(`
${err}
`); 64 | }) 65 | .finally(() => { 66 | response.end(); 67 | mySqlClient.end(); 68 | redisClient.end(true); 69 | mongoDb.close(); 70 | }); 71 | }); 72 | 73 | server.listen(PORT, (err) => { 74 | if (err) { 75 | console.error('Something bad happened: %o', err) 76 | } else { 77 | console.info(`Server is listening on %d`, PORT) 78 | } 79 | }); 80 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | require 'yaml' 2 | VAGRANTFILE_API_VERSION = "2" 3 | 4 | # If you want to use 'nfs' synchronization on Linux systems 5 | # Ubuntu: apt-get -y install nfs-kernel-server nfs-common 6 | # CentOS: yum -y install nfs-utils nfs-utils-lib 7 | # Mac OS X: it should be already pre-installed 8 | 9 | # The host name (you should also change it in the machine/ansible/vars/globals.yml) 10 | HOSTNAME = 'phanbox.local' 11 | ALIASES = %w(www.phanbox.local api.phanbox.local) 12 | 13 | # Allocate hardware resources for the virtual machine 14 | CPU = 4 15 | RAM = 4096 16 | 17 | # I don't think you want to change it... 18 | # In case you do change it you also need change it in "machine/ansible/inventory" 19 | IP_ADDRESS = '10.10.10.10' 20 | 21 | # Check to determine whether we're on a windows or linux/os-x host, 22 | # later on we use this to launch ansible in the supported way 23 | # source: https://stackoverflow.com/questions/2108727/which-in-ruby-checking-if-program-exists-in-path-from-ruby 24 | def which(cmd) 25 | exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : [''] 26 | 27 | ENV['PATH'].split(File::PATH_SEPARATOR).each do |path| 28 | exts.each { |ext| 29 | exe = File.join(path, "#{cmd}#{ext}") 30 | return exe if File.executable? exe 31 | } 32 | end 33 | 34 | return nil 35 | end 36 | 37 | Vagrant.require_version '>= 1.8.5' 38 | Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| 39 | # We cannot use can canonical ubuntu/xenial64 as it doesn't provided vagrant user 40 | # despite to vagrant convention that the default user is named always "vagrant" 41 | # https://bugs.launchpad.net/cloud-images/+bug/1569237 42 | config.vm.box = 'bento/ubuntu-16.04' 43 | config.vm.box_version = '2.3.5' 44 | config.vm.hostname = HOSTNAME 45 | config.vm.network :private_network, :ip => IP_ADDRESS 46 | 47 | #config.ssh.insert_key = false 48 | config.ssh.forward_agent = true 49 | 50 | # Prevent TTY Errors (copied from laravel/homestead: "homestead.rb" file)... By default this is "bash -l" 51 | config.ssh.shell = "bash -c 'BASH_ENV=/etc/profile exec bash'" 52 | 53 | # Setup directories synchronization mode 54 | if Vagrant::Util::Platform.windows? 55 | sync_options = { 56 | :mount_options => ["dmode=775", "fmode=775"], 57 | :owner => 'vagrant', 58 | :group => 'vagrant' 59 | } 60 | else 61 | sync_options = { 62 | :nfs => { :mount_options => ["dmode=775", "fmode=775", "actimeo=2", "lookupcache=non", "rw", "vers=3", "tcp", "fsc"] } 63 | } 64 | end 65 | 66 | config.vm.synced_folder "./machine/", "/vagrant/", sync_options 67 | 68 | # Configure VirtualBox provider 69 | config.vm.provider :virtualbox do |vb| 70 | vb.name = HOSTNAME 71 | 72 | vb.customize ["modifyvm", :id, "--cpus", CPU] 73 | vb.customize ["modifyvm", :id, "--memory", RAM] 74 | vb.customize ["modifyvm", :id, "--ioapic", "on"] 75 | vb.customize ["modifyvm", :id, "--cableconnected1", "on"] 76 | vb.customize ["modifyvm", :id, "--natdnshostresolver1", "on"] 77 | vb.customize ["modifyvm", :id, "--natdnsproxy1", "on"] 78 | vb.customize ["modifyvm", :id, "--nictype1", "virtio"] 79 | vb.customize ["modifyvm", :id, "--nictype2", "virtio"] 80 | vb.customize ["guestproperty", "set", :id, "/VirtualBox/GuestAdd/VBoxService/--timesync-set-threshold", 10000] 81 | vb.customize ["guestproperty", "set", :id, "/VirtualBox/GuestAdd/VBoxService/--timesync-interval", 5000] 82 | end 83 | 84 | # Update "hosts" file for host/guest machines 85 | if Vagrant.has_plugin? 'vagrant-hostmanager' 86 | config.hostmanager.enabled = true 87 | config.hostmanager.manage_host = true 88 | config.hostmanager.manage_guest = true 89 | config.hostmanager.ignore_private_ip = false 90 | config.hostmanager.include_offline = true 91 | 92 | if ALIASES.any? 93 | config.hostmanager.aliases = ALIASES 94 | end 95 | end 96 | 97 | # Run Host Manager provision 98 | config.vm.provision :hostmanager 99 | 100 | # If ansible is in your path it will provision from your HOST machine 101 | # If ansible is not found in the path it will be instaled in the VM and provisioned from there 102 | if which('ansible-playbook') 103 | config.vm.provision "ansible" do |ansible| 104 | ansible.playbook = "machine/ansible/playbook.yml" 105 | ansible.inventory_path = "machine/ansible/inventory/hosts" 106 | ansible.limit = 'all' 107 | end 108 | else 109 | config.vm.provision :shell, path: "machine/ansible/files/ansible.sh" 110 | end 111 | 112 | # Parse ansible variables to extract the name of node.js application service 113 | ansible_vars_path = "#{File.dirname(__FILE__)}/machine/ansible/vars/globals.yml" 114 | ansible_vars = YAML.load_file(ansible_vars_path) 115 | 116 | if ansible_vars.has_key?('app_node') and ansible_vars['app_node'].has_key?('service_name') 117 | # Automatically start node.js application when vagrant launched 118 | app_node_service = ansible_vars['app_node']['service_name'] 119 | config.vm.provision "shell", run: "always", inline: "systemctl restart #{app_node_service}" 120 | end 121 | 122 | # Always make sure cachefilesd is running 123 | config.vm.provision "shell", run: "always", inline: "systemctl start cachefilesd" 124 | end 125 | -------------------------------------------------------------------------------- /machine/ansible/roles/php/tasks/php-fpm.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Set permissions on socket - owner 3 | lineinfile: "dest=/etc/php/7.1/fpm/pool.d/www.conf state=present regexp='^;?listen.owner' line='listen.owner = www-data'" 4 | 5 | - name: Set permissions on socket - group 6 | lineinfile: "dest=/etc/php/7.1/fpm/pool.d/www.conf state=present regexp='^;?listen.group' line='listen.group = www-data'" 7 | 8 | - name: Set permissions on socket - mode 9 | lineinfile: "dest=/etc/php/7.1/fpm/pool.d/www.conf state=present regexp='^;?listen.mode' line='listen.mode = 0660'" 10 | notify: restart php7-fpm 11 | 12 | - name: Ensure timezone is set in fpm php.ini 13 | lineinfile: dest=/etc/php/7.1/fpm/php.ini 14 | regexp='date.timezone =' 15 | line='date.timezone = {{ php_timezone }}' 16 | 17 | - name: Enabling opcache 18 | lineinfile: dest=/etc/php/7.1/fpm/php.ini 19 | regexp='^#?opcache.enable=' 20 | line='opcache.enable=1' 21 | 22 | - name: Opcache - changing revalidate frequency to 0 23 | lineinfile: dest=/etc/php/7.1/fpm/php.ini 24 | regexp='opcache.revalidate_freq=' 25 | line='opcache.revalidate_freq=0' 26 | tags: [ development ] 27 | 28 | - name: Set session.cookie_httponly to `true` 29 | lineinfile: dest=/etc/php/7.1/fpm/php.ini 30 | regexp='session.cookie_httponly(\s)?=' 31 | line='session.cookie_httponly=1' 32 | notify: restart php7-fpm 33 | 34 | - name: Enable session strict mode 35 | lineinfile: dest=/etc/php/7.1/fpm/php.ini 36 | regexp='session.use_strict_mode(\s)?=' 37 | line='session.use_strict_mode = 1' 38 | notify: restart php7-fpm 39 | 40 | - name: Set allow_url_fopen 41 | lineinfile: dest=/etc/php/7.1/fpm/php.ini 42 | regexp='allow_url_fopen(\s)?=' 43 | line='allow_url_fopen = {{ php_allow_url_fopen }}' 44 | notify: restart php7-fpm 45 | 46 | - name: Change soap.wsdl_cache_dir to new directory 47 | lineinfile: dest=/etc/php/7.1/fpm/php.ini 48 | regexp='soap.wsdl_cache_dir(\s)?=' 49 | line='soap.wsdl_cache_dir=/php/cache/wsdl' 50 | notify: restart php7-fpm 51 | 52 | - name: Change upload_tmp_dir path 53 | lineinfile: dest=/etc/php/7.1/fpm/php.ini 54 | regexp='upload_tmp_dir(\s)?=' 55 | line='upload_tmp_dir=/php/cache/upload_tmp' 56 | notify: restart php7-fpm 57 | 58 | - name: Exclude potentially harmfull php functions 59 | lineinfile: dest=/etc/php/7.1/fpm/php.ini 60 | regexp='disable_functions(\s)?=' 61 | line='disable_functions=exec,passthru,shell_exec,system,proc_open,popen' 62 | notify: restart php7-fpm 63 | 64 | - name: Set post_max_size 65 | lineinfile: dest=/etc/php/7.1/fpm/php.ini 66 | regexp='post_max_size(\s)?=' 67 | line='post_max_size = {{ php_post_max_size }}' 68 | notify: restart php7-fpm 69 | 70 | - name: Set upload_max_filesize 71 | lineinfile: dest=/etc/php/7.1/fpm/php.ini 72 | regexp='upload_max_filesize(\s)?=' 73 | line='upload_max_filesize = {{ php_upload_max_filesize }}' 74 | create=yes 75 | notify: restart php7-fpm 76 | 77 | - name: Set memory_limit 78 | lineinfile: dest=/etc/php/7.1/fpm/php.ini 79 | regexp='memory_limit(\s)?=' 80 | line='memory_limit = {{ php_memory_limit }}' 81 | notify: restart php7-fpm 82 | 83 | - name: Set max_execution_time 84 | lineinfile: dest=/etc/php/7.1/fpm/php.ini 85 | regexp='max_execution_time(\s)?=' 86 | line='max_execution_time = {{ php_max_execution_time }}' 87 | notify: restart php7-fpm 88 | 89 | - name: enabling opcache 90 | lineinfile: dest=/etc/php/7.1/fpm/php.ini 91 | regexp='opcache.enable=' 92 | line='opcache.enable={{ php_opcache_enable }}' 93 | insertafter="^[opcache]" 94 | notify: restart php7-fpm 95 | 96 | - name: opcache - changing revalidate frequency 97 | lineinfile: dest=/etc/php/7.1/fpm/php.ini 98 | regexp='opcache.revalidate_freq=' 99 | line='opcache.revalidate_freq={{ php_opcache_revalidate_freq }}' 100 | insertafter="^[opcache]" 101 | notify: restart php7-fpm 102 | 103 | - name: opcache - changing validate timestamps 104 | lineinfile: dest=/etc/php/7.1/fpm/php.ini 105 | regexp='opcache.validate_timestamps=' 106 | line='opcache.validate_timestamps={{ php_opcache_opcache_validate_timestamps }}' 107 | insertafter="^[opcache]" 108 | notify: restart php7-fpm 109 | 110 | - name: opcache - changing max accelerated files 111 | lineinfile: dest=/etc/php/7.1/fpm/php.ini 112 | regexp='opcache.max_accelerated_files=' 113 | line='opcache.max_accelerated_files={{ php_opcache_max_accelerated_files }}' 114 | insertafter="^[opcache]" 115 | notify: restart php7-fpm 116 | 117 | - name: opcache - memory consumption 118 | lineinfile: dest=/etc/php/7.1/fpm/php.ini 119 | regexp='opcache.memory_consumption=' 120 | line='opcache.memory_consumption={{ php_opcache_memory_consumption }}' 121 | insertafter="^[opcache]" 122 | notify: restart php7-fpm 123 | 124 | - name: opcache - interned strings buffer 125 | lineinfile: dest=/etc/php/7.1/fpm/php.ini 126 | regexp='opcache.interned_strings_buffer=' 127 | line='opcache.interned_strings_buffer={{ php_opcache_interned_strings_buffer }}' 128 | insertafter="^[opcache]" 129 | notify: restart php7-fpm 130 | 131 | - name: opcache - fast shutdown 132 | lineinfile: dest=/etc/php/7.1/fpm/php.ini 133 | regexp='opcache.fast_shutdown=' 134 | line='opcache.fast_shutdown={{ php_opcache_fast_shutdown }}' 135 | insertafter="^[opcache]" 136 | notify: restart php7-fpm 137 | -------------------------------------------------------------------------------- /machine/application/app-node/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "phanbox-app-node", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "dependencies": { 6 | "bignumber.js": { 7 | "version": "3.1.2", 8 | "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-3.1.2.tgz", 9 | "integrity": "sha1-8725mtUmihX8HwvtL7AY4mk/4jY=" 10 | }, 11 | "bluebird": { 12 | "version": "3.5.0", 13 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.0.tgz", 14 | "integrity": "sha1-eRQg1/VR7qKJdFOop3ZT+WYG1nw=" 15 | }, 16 | "bson": { 17 | "version": "1.0.4", 18 | "resolved": "https://registry.npmjs.org/bson/-/bson-1.0.4.tgz", 19 | "integrity": "sha1-k8ENOeqltYQVy8QFLz5T5WKwtyw=" 20 | }, 21 | "buffer-shims": { 22 | "version": "1.0.0", 23 | "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", 24 | "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=" 25 | }, 26 | "core-util-is": { 27 | "version": "1.0.2", 28 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 29 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 30 | }, 31 | "double-ended-queue": { 32 | "version": "2.1.0-0", 33 | "resolved": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz", 34 | "integrity": "sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw=" 35 | }, 36 | "es6-promise": { 37 | "version": "3.2.1", 38 | "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.2.1.tgz", 39 | "integrity": "sha1-7FYjOGgDKQkgcXDDlEjiREndH8Q=" 40 | }, 41 | "inherits": { 42 | "version": "2.0.3", 43 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 44 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 45 | }, 46 | "isarray": { 47 | "version": "0.0.1", 48 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", 49 | "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" 50 | }, 51 | "moment": { 52 | "version": "2.18.1", 53 | "resolved": "https://registry.npmjs.org/moment/-/moment-2.18.1.tgz", 54 | "integrity": "sha1-w2GT3Tzhwu7SrbfIAtu8d6gbHA8=" 55 | }, 56 | "mongodb": { 57 | "version": "2.2.29", 58 | "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.29.tgz", 59 | "integrity": "sha512-MrQvIsN6zN80I4hdFo8w46w51cIqD2FJBGsUfApX9GmjXA1aCclEAJbOHaQWjCtabeWq57S3ECzqEKg/9bdBhA==", 60 | "dependencies": { 61 | "isarray": { 62 | "version": "1.0.0", 63 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 64 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" 65 | }, 66 | "readable-stream": { 67 | "version": "2.2.7", 68 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.7.tgz", 69 | "integrity": "sha1-BwV6y+JGeyIELTb5jFrVBwVOlbE=" 70 | }, 71 | "string_decoder": { 72 | "version": "1.0.2", 73 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.2.tgz", 74 | "integrity": "sha1-sp4fThEl+pehA4K4pTNze3SR4Xk=" 75 | } 76 | } 77 | }, 78 | "mongodb-core": { 79 | "version": "2.1.13", 80 | "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.13.tgz", 81 | "integrity": "sha512-mbcvqLLZwVcpTrsfBDY3hRNk2SDNJWOvKKxFJSc0pnUBhYojymBc/L0THfQsWwKJrkb2nIXSjfFll1mG/I5OqQ==" 82 | }, 83 | "mysql": { 84 | "version": "2.13.0", 85 | "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.13.0.tgz", 86 | "integrity": "sha1-mY8fjKRuLj3XFJzpgkE2U5hqrkc=" 87 | }, 88 | "process-nextick-args": { 89 | "version": "1.0.7", 90 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", 91 | "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" 92 | }, 93 | "readable-stream": { 94 | "version": "1.1.14", 95 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", 96 | "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=" 97 | }, 98 | "redis": { 99 | "version": "2.7.1", 100 | "resolved": "https://registry.npmjs.org/redis/-/redis-2.7.1.tgz", 101 | "integrity": "sha1-fVb3h1uYsgQQtxU58dh47Vjr9Go=" 102 | }, 103 | "redis-commands": { 104 | "version": "1.3.1", 105 | "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.3.1.tgz", 106 | "integrity": "sha1-gdgm9F+pyLIBH0zXoP5ZfSQdRCs=" 107 | }, 108 | "redis-parser": { 109 | "version": "2.6.0", 110 | "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-2.6.0.tgz", 111 | "integrity": "sha1-Uu0J2srBCPGmMcB+m2mUHnoZUEs=" 112 | }, 113 | "require_optional": { 114 | "version": "1.0.1", 115 | "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", 116 | "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==" 117 | }, 118 | "resolve-from": { 119 | "version": "2.0.0", 120 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", 121 | "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" 122 | }, 123 | "safe-buffer": { 124 | "version": "5.0.1", 125 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.0.1.tgz", 126 | "integrity": "sha1-0mPKVGls2KMGtcplUekt5XkY++c=" 127 | }, 128 | "semver": { 129 | "version": "5.3.0", 130 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", 131 | "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" 132 | }, 133 | "sqlstring": { 134 | "version": "2.2.0", 135 | "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.2.0.tgz", 136 | "integrity": "sha1-wxNcTqirzX5+50GklmqJHYak8ZE=" 137 | }, 138 | "string_decoder": { 139 | "version": "0.10.31", 140 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", 141 | "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" 142 | }, 143 | "util-deprecate": { 144 | "version": "1.0.2", 145 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 146 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 147 | } 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Phanbox - the basic vagrant machine for Node.js and PHP applications 2 | 3 | ### Installation 4 | 5 | * Install [Virtual Box](https://www.virtualbox.org/wiki/Downloads) (>= 5.0 version) 6 | * Install [Vagrant](https://www.vagrantup.com/downloads.html) (>=1.8.5 version) 7 | * Install [Vagrant Host Manager plugin](https://github.com/devopsgroup-io/vagrant-hostmanager) (`vagrant plugin install vagrant-hostmanager`) 8 | * Install [Vagrant Virtual Box guest additions plugin](https://github.com/dotless-de/vagrant-vbguest) (`vagrant plugin install vagrant-vbguest`) 9 | * If your application has too many composer dependencies and github asks for authorization then you need to copy `./ansible/vars/locals.yml.dist` to `./ansible/vars/locals.yml` and put there your GitHub token. 10 | * Run `vagrant up` 11 | * Wait until provisioning is finished... 12 | * If you have Linux or Mac OS X then you'd better perform `vagrant reload` after provisioning is finished to get maximum performance of your vagrant machine 13 | 14 | ### Regular usage: 15 | 16 | * Stop machine: `vagrant suspend` or `vagrant halt` (the later one is the complete shut down) 17 | * Start machine: `vagrant up` 18 | * Reload machine: `vagrant reload` 19 | * Re-provision machine: `vagrant provision` (if any ansible provisioning configurations were changed or updated) 20 | 21 | #### Test virtual hosts: 22 | 23 | * [http://[www].phanbox.local](http://phanbox.local) - PHP application home page (index.php). It also contains healthcheck logic to verify that PHP app is successfully connected to MySQL, MongoDB and Redis. 24 | * [http://phanbox.local/phpinfo.php](http://phanbox.local/phpinfo.php) - PHP info page 25 | * [http://phanbox.local/index.html](http://phanbox.local/index.html) - Static HTML page served by NGINX 26 | * [http://phanbox.local:3000](http://phanbox.local:3000) - Node.js application home page. It also contains healthcheck logic to verify that Node.js app is successfully connected to MySQL, MongoDB and Redis. 27 | 28 | ### What does the box consist of? 29 | 30 | The box is provisioned using [Ansible](https://www.ansible.com/) tool. 31 | The local host directory `./machine` is mounted to `/vagrant` directory inside vagrant machine 32 | The ansible playbook, roles, tasks and other resources are residing in `machine/ansible` directory, while the application specific code - inside `machine/application`. 33 | The provisioned vagrant machine has following items: 34 | 35 | * Ubuntu Xenial64 (16.04 LTS) 36 | * PHP application 37 | - PHP-FPM 7.1 38 | - Nginx 39 | - xDebug 40 | - Composer 41 | - Application root: `machine/application/app-php` 42 | - Document root: `machine/application/app-php/public` 43 | - Environment (APP_ENV): 'development' 44 | * Node.js application 45 | - Node.js 8.x 46 | - npm 5.x 47 | - yarn 48 | - nodemon, gulp, grunt (installed globally) 49 | - Application root: `machine/application/app-node` 50 | - The application is run using `npm start` command 51 | - Port: 3000 52 | - Environment (NODE_ENV): 'development' 53 | - Daemonized with Systemd service i.e. when you are inside vagrant machine you may start/stop/restart it with `sudo service app-node start/stop/restart` command 54 | * MySQL Percona 5.7 55 | * MongoDB 3.4 56 | * Redis 3.x 57 | * [NFS + Cachefilesd](http://chase-seibert.github.io/blog/2014/03/09/vagrant-cachefilesd.html) - for Linux and Mac OS X NFS folder synchronization is enabled 58 | 59 | It may be easily extended and modified with a little knowledge of Ansible. 60 | 61 | #### Vagrant machine default settings (could be changed in Vagrantfile) 62 | 63 | - Hostname: **phanbox.local** 64 | - Allocated CPUs: **4** (cores) 65 | - Allocated Memory: **4096** (MB) 66 | - IP address: **10.10.10.10** 67 | 68 | #### PHP Application 69 | 70 | If you do not need PHP application: 71 | 72 | - Go to `machine/ansible/playbook.yml` and delete **app-php** role from the list 73 | - Go to `machine/ansible/vars/globals.yml` and delete **app_php** section 74 | 75 | If you want to customize it then you may take a look at **app_php** section to modify application/document roots, server name. 76 | It is pretty basic application and you may want to add provisioning logic to it. It is failrly easy to do if you have a little knowledge of Ansible. 77 | All you need is to go to the `machine/ansible/roles/app-php` and add there whatever tasks and logic you need. 78 | 79 | - See machine/ansible/vars/globals.yml 80 | 81 | #### Node.js Application 82 | 83 | If you do not need Node.js application then: 84 | 85 | - Go to `machine/ansible/playbook.yml` and delete **app-node** role from the list 86 | - Go to `machine/ansible/vars/globals.yml` and delete **app_node** section 87 | 88 | To run Node.js application automatically there is systemd service created which is started automatically when vagrant machine is launched. 89 | If you want to interact with the service the you shoud do: 90 | 91 | - `vagrant ssh` 92 | - `sudo service app-node restart` - will restart the node.js app 93 | - `sudo service app-node stop` - will stop the node.js app (for example, you want to run it manually instead) 94 | - `sudo service app-node start` - will start the sevice again 95 | - service logs may be found at `/var/log/app-node.log` 96 | 97 | If you want to customize it then you may take a look at **app_node** section to modify application root, port, systemd service name, environment. 98 | It is pretty basic application and you may want to add provisioning logic to it. It is failrly easy to do if you have a little knowledge of Ansible. 99 | All you need is to go to the `machine/ansible/roles/app-node` and add there whatever tasks and logic you need. 100 | 101 | #### MySQL 102 | 103 | If you do not need MySQL for your application: 104 | 105 | - Go to `machine/ansible/playbook.yml` and delete **mysql** role from the list 106 | - Go to `machine/ansible/vars/globals.yml` and delete **mysql** section 107 | 108 | The default parameters for mysql server: 109 | 110 | - User: **app** 111 | - Password: **app** 112 | - Database: **app** 113 | - ROOT PASSWORD: **password** 114 | - Database dump file (will be imported only once during the first provisioning): `machine/dump/mysql.sql` 115 | 116 | If you want to customize these parameters see `machine/ansible/vars/globals.yml` **mysql** section 117 | 118 | #### MongoDB 119 | 120 | If you do not need MongoDB for your application: 121 | 122 | - Go to `machine/ansible/playbook.yml` and delete **mongodb** role from the list 123 | - Go to `machine/ansible/vars/globals.yml` and delete **mongodb** section 124 | 125 | The default parameters for MongoDB server: 126 | 127 | - User: **app** 128 | - Password: **app** 129 | - Database: **app** 130 | - ROOT PASSWORD: **password** 131 | - Database dump directory (will be imported only once during the first provisioning): `machine/dump/mongodb` - 132 | this directory should contain 1 file per MongoDB collection where the file name is a collection name (with omitted .json extension) 133 | - If your MongoDB dump was exported without [--jsonArray flag](https://docs.mongodb.com/manual/reference/program/mongoexport/#cmdoption-jsonarray) then you should set `dump_array_mode: true` in `machine/ansible/vars/globals.yml` file. 134 | 135 | If you want to customize these parameters see `machine/ansible/vars/globals.yml` **mysql** section 136 | -------------------------------------------------------------------------------- /machine/application/app-php/composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "48c7bf5f3a6f2f228f984faa7fbaa9ae", 8 | "packages": [ 9 | { 10 | "name": "mongodb/mongodb", 11 | "version": "1.1.2", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/mongodb/mongo-php-library.git", 15 | "reference": "a307dd60e71e1291c60927ea4f3a1905146063f5" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/mongodb/mongo-php-library/zipball/a307dd60e71e1291c60927ea4f3a1905146063f5", 20 | "reference": "a307dd60e71e1291c60927ea4f3a1905146063f5", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "ext-mongodb": "^1.2.0", 25 | "php": ">=5.4" 26 | }, 27 | "require-dev": { 28 | "phpunit/phpunit": "^4.8" 29 | }, 30 | "type": "library", 31 | "autoload": { 32 | "psr-4": { 33 | "MongoDB\\": "src/" 34 | }, 35 | "files": [ 36 | "src/functions.php" 37 | ] 38 | }, 39 | "notification-url": "https://packagist.org/downloads/", 40 | "license": [ 41 | "Apache-2.0" 42 | ], 43 | "authors": [ 44 | { 45 | "name": "Jeremy Mikola", 46 | "email": "jmikola@gmail.com" 47 | }, 48 | { 49 | "name": "Hannes Magnusson", 50 | "email": "bjori@mongodb.com" 51 | }, 52 | { 53 | "name": "Derick Rethans", 54 | "email": "github@derickrethans.nl" 55 | } 56 | ], 57 | "description": "MongoDB driver library", 58 | "homepage": "https://jira.mongodb.org/browse/PHPLIB", 59 | "keywords": [ 60 | "database", 61 | "driver", 62 | "mongodb", 63 | "persistence" 64 | ], 65 | "time": "2017-02-16T18:40:32+00:00" 66 | }, 67 | { 68 | "name": "nesbot/carbon", 69 | "version": "1.22.1", 70 | "source": { 71 | "type": "git", 72 | "url": "https://github.com/briannesbitt/Carbon.git", 73 | "reference": "7cdf42c0b1cc763ab7e4c33c47a24e27c66bfccc" 74 | }, 75 | "dist": { 76 | "type": "zip", 77 | "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/7cdf42c0b1cc763ab7e4c33c47a24e27c66bfccc", 78 | "reference": "7cdf42c0b1cc763ab7e4c33c47a24e27c66bfccc", 79 | "shasum": "" 80 | }, 81 | "require": { 82 | "php": ">=5.3.0", 83 | "symfony/translation": "~2.6 || ~3.0" 84 | }, 85 | "require-dev": { 86 | "friendsofphp/php-cs-fixer": "~2", 87 | "phpunit/phpunit": "~4.0 || ~5.0" 88 | }, 89 | "type": "library", 90 | "extra": { 91 | "branch-alias": { 92 | "dev-master": "1.23-dev" 93 | } 94 | }, 95 | "autoload": { 96 | "psr-4": { 97 | "Carbon\\": "src/Carbon/" 98 | } 99 | }, 100 | "notification-url": "https://packagist.org/downloads/", 101 | "license": [ 102 | "MIT" 103 | ], 104 | "authors": [ 105 | { 106 | "name": "Brian Nesbitt", 107 | "email": "brian@nesbot.com", 108 | "homepage": "http://nesbot.com" 109 | } 110 | ], 111 | "description": "A simple API extension for DateTime.", 112 | "homepage": "http://carbon.nesbot.com", 113 | "keywords": [ 114 | "date", 115 | "datetime", 116 | "time" 117 | ], 118 | "time": "2017-01-16T07:55:07+00:00" 119 | }, 120 | { 121 | "name": "symfony/polyfill-mbstring", 122 | "version": "v1.4.0", 123 | "source": { 124 | "type": "git", 125 | "url": "https://github.com/symfony/polyfill-mbstring.git", 126 | "reference": "f29dca382a6485c3cbe6379f0c61230167681937" 127 | }, 128 | "dist": { 129 | "type": "zip", 130 | "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/f29dca382a6485c3cbe6379f0c61230167681937", 131 | "reference": "f29dca382a6485c3cbe6379f0c61230167681937", 132 | "shasum": "" 133 | }, 134 | "require": { 135 | "php": ">=5.3.3" 136 | }, 137 | "suggest": { 138 | "ext-mbstring": "For best performance" 139 | }, 140 | "type": "library", 141 | "extra": { 142 | "branch-alias": { 143 | "dev-master": "1.4-dev" 144 | } 145 | }, 146 | "autoload": { 147 | "psr-4": { 148 | "Symfony\\Polyfill\\Mbstring\\": "" 149 | }, 150 | "files": [ 151 | "bootstrap.php" 152 | ] 153 | }, 154 | "notification-url": "https://packagist.org/downloads/", 155 | "license": [ 156 | "MIT" 157 | ], 158 | "authors": [ 159 | { 160 | "name": "Nicolas Grekas", 161 | "email": "p@tchwork.com" 162 | }, 163 | { 164 | "name": "Symfony Community", 165 | "homepage": "https://symfony.com/contributors" 166 | } 167 | ], 168 | "description": "Symfony polyfill for the Mbstring extension", 169 | "homepage": "https://symfony.com", 170 | "keywords": [ 171 | "compatibility", 172 | "mbstring", 173 | "polyfill", 174 | "portable", 175 | "shim" 176 | ], 177 | "time": "2017-06-09T14:24:12+00:00" 178 | }, 179 | { 180 | "name": "symfony/translation", 181 | "version": "v3.3.2", 182 | "source": { 183 | "type": "git", 184 | "url": "https://github.com/symfony/translation.git", 185 | "reference": "dc3b2a0c6cfff60327ba1c043a82092735397543" 186 | }, 187 | "dist": { 188 | "type": "zip", 189 | "url": "https://api.github.com/repos/symfony/translation/zipball/dc3b2a0c6cfff60327ba1c043a82092735397543", 190 | "reference": "dc3b2a0c6cfff60327ba1c043a82092735397543", 191 | "shasum": "" 192 | }, 193 | "require": { 194 | "php": ">=5.5.9", 195 | "symfony/polyfill-mbstring": "~1.0" 196 | }, 197 | "conflict": { 198 | "symfony/config": "<2.8", 199 | "symfony/yaml": "<3.3" 200 | }, 201 | "require-dev": { 202 | "psr/log": "~1.0", 203 | "symfony/config": "~2.8|~3.0", 204 | "symfony/intl": "^2.8.18|^3.2.5", 205 | "symfony/yaml": "~3.3" 206 | }, 207 | "suggest": { 208 | "psr/log": "To use logging capability in translator", 209 | "symfony/config": "", 210 | "symfony/yaml": "" 211 | }, 212 | "type": "library", 213 | "extra": { 214 | "branch-alias": { 215 | "dev-master": "3.3-dev" 216 | } 217 | }, 218 | "autoload": { 219 | "psr-4": { 220 | "Symfony\\Component\\Translation\\": "" 221 | }, 222 | "exclude-from-classmap": [ 223 | "/Tests/" 224 | ] 225 | }, 226 | "notification-url": "https://packagist.org/downloads/", 227 | "license": [ 228 | "MIT" 229 | ], 230 | "authors": [ 231 | { 232 | "name": "Fabien Potencier", 233 | "email": "fabien@symfony.com" 234 | }, 235 | { 236 | "name": "Symfony Community", 237 | "homepage": "https://symfony.com/contributors" 238 | } 239 | ], 240 | "description": "Symfony Translation Component", 241 | "homepage": "https://symfony.com", 242 | "time": "2017-05-22T07:42:36+00:00" 243 | } 244 | ], 245 | "packages-dev": [], 246 | "aliases": [], 247 | "minimum-stability": "stable", 248 | "stability-flags": [], 249 | "prefer-stable": false, 250 | "prefer-lowest": false, 251 | "platform": { 252 | "php": "^7.1" 253 | }, 254 | "platform-dev": [] 255 | } 256 | --------------------------------------------------------------------------------