Development Environment with Puphpet
General
I've been using PHP and the LAMP stack as my main environment since 2009.
At the beginning of every project I had same issues related to a VM preparation.
I found several tools on the market which I tested: Vagrant, Chef, Ansible, Puppet - these all are great and help prepare the development environment automatization.
Today, I want to show a helpful tool (esspecialy from the PHP developer point of view): Puphpet
Puphpet is a configurator for Vagrant and Puppet. It prepares a package with all necessary files to run a new virtual machine with all required components by a PHP application.
In short, Puphpet helps to prepare a local development environment without detailed knowledge about Vagrant and Puppet.
Configuration
The following example shows how to run a PHP application based on the Symfony framework.
The app uses LAMP.
Requirements
You need install Vagrant and Virtualbox to finish that example.
Puphpet Creator
General options
Go to the https://puphpet.com/ website and click the green button.
On the first step, I chose the Virtualbox provider (you can use VmWare solutions as well) and the Ubuntu Xenial 16.04 LTS x64 operating system.
Now is the time to set machines. I need an only one machine in the example, but that configurator gives us the possibility to specify as many as we need.
To create more advanced configuration we can add more machines. The case would look like below:
- I need an e-commerce system
- I need a PIM solution
- In the configurator, I can create to separated machines to test integrations between those etc.
Have a look at the following picture:
The first and the second input specify identification. It doesn't really matter now, you can fill as you like. Ip Address input specifies an address which we can use by ssh or http to connect the new VM.
In this form are also two values responsible for the memory amount (assigned to the VM) and a number of CPU's assigned to the machine (no worries you can change it later).
A crucial step in the configuration process is setting-up shared folders.
I want to share the /var/www
directory between the host and VM.
Files used by the application I will put into the ../www
directory. Also, I'd like to share /vagrant
folder with my local machine. The directory will contain all data from the puphpet project directory.
At the end I will see php application files in /var/www
and puphpet application files in the /vagrant
location.
To share files between my local system (in my case it's MacOs) and the Virtual Machine environment (Ubuntu) I used shared folders option, like below.
Packages
What is amazing, Puphpet has a packages configurator.
Let's say that we need several packages installed on our VM, you can update that list also after we finish the configurator.
To run my app I need following packages
- wkhtmltopdf - my app would use it to generate pdf documents based on website views
- htop, vim
- zip
Note that you don't have to specify any php extensions here, there is a step later which does it.
Users and Groups
The netx step precise groups and users created in the VM.
I need an only one user named: testapp. See the picture below to find how to make it.
Cron jobs
I missed steps Locale, Firewall and Resolv in that usage showcase (left default values) adn went directly to the Cron Jobs step.
The cron job configurator defines a scheduler for scripts available in the VM.
I know that /var/www
directory will be shared with my ../www
folder, therefore I can specify a script run automatically every second hour.
Apache Installation
Now I want to configure the apache instance (look that you can choose Nginx if you prefer).
For the example needs I add the only one host, let's say that I want to run my application using the http://testapp.dev
address and I put my public app file into the /var/www/testapp/web
directory.
And basically, that's it - it will create all necessary file to tun the host. What is nice, vagrant takes care of the /etc/hosts/
file update.
PHP Configuration
Here we're able to specify the php version and as I've mentioned before - php extensions.
I added few modules required by my app.
Find all available php modules here: https://launchpad.net/~ondrej/+archive/ubuntu/php/
Here I also specified php-fpm
settings, actually I used the default values but here is the right place to change it. At the end, I also checked the composer installation to improve the automatization process.
Mysql / Mariadb
The last step I'm going to use is the database setup.
I want to create an initial database used by my app using Mariadb (a MySql fork).
Other Steps and Download
Of course, there are a lot of steps you can configure like: Solr, Redis and so on but now is enough to make a test application based on that configuration. Go to the last step: Download Your Customized Archive.
Here is the place where we can download the config puphpet module file or all projects files.
Let's click on the green button
And create somewhere two folders. I've chosen following paths:
~/testapp/vagrant
~/testapp/www
Unpack all downloaded file into the testapp/vagrant
directory.
Config.yaml
The only one file generated by the configurator is located in the vagrant/puphpet/config.yaml
path.
Our file should look like below:
vagrantfile:
target: local
vm:
provider:
local:
box: puphpet/ubuntu1604-x64
box_url: 'false'
box_version: '0'
chosen_virtualizer: virtualbox
virtualizers:
virtualbox:
modifyvm:
natdnshostresolver1: false
showgui: 0
vmware:
numvcpus: 1
parallels:
linked_clone: 0
check_guest_tools: 0
update_guest_tools: 0
machines:
vflm_k4itnhhid5s4:
id: machine1
hostname: machine1.puphpet
network:
private_network: 192.168.56.102
forwarded_port:
vflmnfp_j24v5o08cywg:
host: '6637'
guest: '22'
memory: '2048'
cpus: '4'
provision:
puppet:
manifests_path: puphpet/puppet/manifests
module_path:
- puphpet/puppet/modules
- puphpet/puppet/manifests
options:
- '--verbose'
- '--hiera_config /vagrant/puphpet/puppet/hiera.yaml'
synced_folder:
vflsf_8wdfqwrda380:
owner: www-data
group: www-data
source: ./
target: /vagrant
sync_type: nfs
smb:
smb_host: ''
smb_username: ''
smb_password: ''
mount_options:
dir_mode: '0775'
file_mode: '0664'
rsync:
args:
- '--verbose'
- '--archive'
- '-z'
exclude:
- .vagrant/
- .git/
auto: 'true'
vflsf_20wd8du0kjef:
owner: www-data
group: www-data
source: ../www
target: /var/www
sync_type: nfs
smb:
smb_host: ''
smb_username: ''
smb_password: ''
mount_options:
dir_mode: '0775'
file_mode: '0664'
rsync:
args:
- '--verbose'
- '--archive'
- '-z'
exclude:
- .vagrant/
- .git/
auto: 'true'
usable_port_range:
start: 10200
stop: 10500
post_up_message: ''
ssh:
host: 'false'
port: 'false'
private_key_path: 'false'
username: vagrant
guest_port: 'false'
keep_alive: '1'
forward_agent: 'false'
forward_x11: 'false'
shell: 'bash -l'
insert_key: 'false'
vagrant:
host: detect
proxy:
http: ''
https: ''
ftp: ''
no_proxy: ''
server:
install: '1'
packages:
- vim
- htop
- wkhtmltopdf
- zip
users_groups:
install: '1'
groups:
- testapp
users:
- '{testapp}{testapp}'
locale:
install: '1'
settings:
default_locale: en_US.UTF-8
locales:
- en_GB.UTF-8
- en_US.UTF-8
timezone: UTC
firewall:
install: '1'
rules: { }
resolv:
install: '1'
nameservers:
- 8.8.8.8
- 8.8.4.4
domainname: ''
searchpath: { }
cron:
install: '1'
jobs:
cj_prs7zkvw7g1b:
name: 'testapp jobs'
user: vagrant
command: 'php /var/www//testapp/cron.php > /dev/null'
minute: '1'
hour: '*/2'
weekday: '*'
month: '*'
monthday: ''
nginx:
install: '0'
settings:
version: present
default_vhost: 1
proxy_buffers: '4 256k'
proxy_buffer_size: 128k
proxy_connect_timeout: 600s
proxy_send_timeout: 600s
proxy_read_timeout: 600s
names_hash_bucket_size: 128
upstreams: { }
vhosts:
nxv_n087wiye8ku9:
server_name: awesome.dev
server_aliases:
- www.awesome.dev
www_root: /var/www/awesome
listen_port: '80'
client_max_body_size: 1m
ssl: '0'
locations:
nxvl_ffz4010gqxpk:
www_root: /var/www/awesome/web
location: /
autoindex: 'off'
internal: 'false'
index_files:
- index.html
- index.php
- app.php
try_files:
- $uri
- $uri/
- /index.php$is_args$args
- /app.php$is_args$args
fastcgi: ''
fastcgi_index: ''
fastcgi_split_path: ''
proxy: ''
proxy_redirect: ''
nxvl_ekxxfmbtwfxp:
www_root: /var/www/awesome/web
location: '~ ^/(app_dev|config)\.php(/|$)'
autoindex: 'off'
internal: 'false'
try_files:
- $uri
- $uri/
- /app_dev.php$is_args$args
fastcgi: '127.0.0.1:9000'
fastcgi_index: app_dev.php
fastcgi_split_path: '^(.+\.php)(/.*)$'
fast_cgi_params_extra:
- 'SCRIPT_FILENAME $document_root$fastcgi_script_name'
- 'APP_ENV dev'
set:
- '$path_info $fastcgi_path_info'
proxy: ''
proxy_redirect: ''
nxvl_kiz7c855rr19:
www_root: /var/www/awesome/web
location: '~ ^/index\.php(/|$)'
autoindex: 'off'
internal: 'false'
try_files:
- $uri
- $uri/
- /index.php$is_args$args
fastcgi: '127.0.0.1:9000'
fastcgi_index: index.php
fastcgi_split_path: '^(.+\.php)(/.*)$'
fast_cgi_params_extra:
- 'SCRIPT_FILENAME $document_root$fastcgi_script_name'
set:
- '$path_info $fastcgi_path_info'
proxy: ''
proxy_redirect: ''
nxvl_4x0fk1jrwczd:
www_root: /var/www/awesome/web
location: '~ ^/app\.php(/|$)'
autoindex: 'off'
internal: 'false'
try_files:
- $uri
- $uri/
- /app.php$is_args$args
fastcgi: '127.0.0.1:9000'
fastcgi_index: app.php
fastcgi_split_path: '^(.+\.php)(/.*)$'
fast_cgi_params_extra:
- 'SCRIPT_FILENAME $document_root$fastcgi_script_name'
- 'APP_ENV prod'
set:
- '$path_info $fastcgi_path_info'
proxy: ''
proxy_redirect: ''
proxies: { }
apache:
install: '1'
settings:
version: 2.4
user: www-data
group: www-data
default_vhost: true
manage_user: false
manage_group: false
sendfile: 0
modules:
- proxy_fcgi
- rewrite
vhosts:
av_ds7c9tnjwhe7:
servername: testapp.dev
docroot: /var/www/testapp/web
port: '80'
setenvif:
- 'Authorization "(.*)" HTTP_AUTHORIZATION=$1'
custom_fragment: ''
ssl: '0'
ssl_cert: LETSENCRYPT
ssl_key: LETSENCRYPT
ssl_chain: LETSENCRYPT
ssl_certs_dir: LETSENCRYPT
ssl_protocol: ''
ssl_cipher: ''
directories:
avd_rt2ki1ql2fu5:
path: /var/www/testapp/web
directoryindex: 'index.php app.dev app.php'
options:
- Indexes
- FollowSymlinks
- MultiViews
allow_override:
- All
require:
- 'all granted'
custom_fragment: ''
provider: directory
files_match:
avfm_v71rd527gjtf:
path: (app_dev|config)\.php$
sethandler: 'proxy:fcgi://127.0.0.1:9000'
setenv:
- 'APP_ENV dev'
custom_fragment: ''
provider: filesmatch
avfm_qy6m6xg433l6:
path: app\.php$
sethandler: 'proxy:fcgi://127.0.0.1:9000'
setenv:
- 'APP_ENV prod'
custom_fragment: ''
provider: filesmatch
avfm_cb8wrbi2n6zb:
path: \.php$
sethandler: 'proxy:fcgi://127.0.0.1:9000'
custom_fragment: ''
provider: filesmatch
letsencrypt:
install: '1'
settings:
email: ''
webserver_service: ''
domains: { }
php:
install: '1'
settings:
version: '7.1'
modules:
php:
- cli
- intl
- xml
- curl
- bz2
- mysql
- geoip
pear: { }
pecl: { }
ini:
display_errors: 'On'
error_reporting: '-1'
session.save_path: /var/lib/php/session
date.timezone: UTC
fpm_ini:
error_log: /var/log/php-fpm.log
fpm_pools:
phpfp_ebvr4hi3kq17:
ini:
prefix: www
listen: '127.0.0.1:9000'
security.limit_extensions: .php
user: www-user
group: www-data
composer: '1'
composer_home: ''
xdebug:
install: '1'
settings:
xdebug.default_enable: '1'
xdebug.remote_autostart: '0'
xdebug.remote_connect_back: '1'
xdebug.remote_enable: '1'
xdebug.remote_handler: dbgp
xdebug.remote_port: '9000'
blackfire:
install: '0'
settings:
server_id: ''
server_token: ''
agent:
http_proxy: ''
https_proxy: ''
log_file: stderr
log_level: '1'
php:
agent_timeout: '0.25'
log_file: ''
log_level: '1'
xhprof:
install: '0'
wpcli:
install: '0'
version: v1.1.0
drush:
install: '0'
version: 8.0.5
ruby:
install: '1'
versions:
rv_fgahfoxuxm8m:
default: '1'
bundler: '1'
version: 2.3.1
gems:
- [email protected]
- [email protected]
- [email protected]
python:
install: '1'
packages: { }
versions: { }
nodejs:
install: '0'
settings:
version: '6'
npm_packages: { }
mariadb:
install: '1'
settings:
version: '10.1'
root_password: '123'
override_options: { }
users:
mariadbnu_9ujhdpfj2d60:
name: testapp
password: '123'
databases:
mariadbnd_6bxe69ouot9n:
name: testapp
sql: ''
grants:
mariadbng_z4drxt7vpk11:
user: testapp
table: '*.*'
privileges:
- ALL
mysql:
install: '0'
settings:
version: '5.7'
root_password: '123'
override_options: { }
users:
mysqlnu_74n6vlw5x1vr:
name: dbuser
password: '123'
databases:
mysqlnd_w1gyqiltk87y:
name: dbname
sql: ''
grants:
mysqlng_4nlv2f7bql9c:
user: dbuser
table: '*.*'
privileges:
- ALL
postgresql:
install: '0'
settings:
global:
encoding: UTF8
version: '9.6'
server:
postgres_password: '123'
databases: { }
users: { }
grants: { }
mongodb:
install: '0'
settings:
bind_ip: 127.0.0.1
port: '27017'
globals:
version: 2.6.0
databases: { }
redis:
install: '0'
settings:
port: '6379'
sqlite:
install: '0'
databases: { }
mailhog:
install: '0'
settings:
smtp_ip: 0.0.0.0
smtp_port: 1025
http_ip: 0.0.0.0
http_port: '8025'
path: /usr/local/bin/mailhog
beanstalkd:
install: '0'
settings:
listenaddress: 0.0.0.0
listenport: '11300'
maxjobsize: '65535'
maxconnections: '1024'
binlogdir: /var/lib/beanstalkd/binlog
binlogfsync: null
binlogsize: '10485760'
beanstalk_console: 0
rabbitmq:
install: '0'
settings:
port: '5672'
users: { }
vhosts: { }
plugins: { }
elastic_search:
install: '0'
settings:
version: 2.3.1
java_install: true
instances:
esi_299dbdf64vje:
name: es-01
solr:
install: '0'
settings:
version: 5.5.2
port: '8984'
As you probably have already realized, the configurator is just a gui for the generated file. If you need change something just edit it or put it again into the https://puphpet.com/ (drag & drop works) to load values again and add something.
Run the Machine
To run the machine go to the vagrant
using a terminal and use the vagrant up
command.
Meantime when vagrant is running the VM put someting into the www/testapp/web/index.php
location.
I added the following code:
<?php
phpinfo();
To check if machine is working properly use vagrant status
.
To connect by ssh use vagrant ssh
.
To check if everything has been resolved properly so far just go to the http://testapp.dev. You should see the phpinfo page like that:
I hope you will enjoy the tool as much as I do.
Next time I will show how to extend Puppet by new instructions - I will deploy my application using the configuration I created here.
Bests!
Congratulations @egoto! You received a personal award!
You can view your badges on your Steem Board and compare to others on the Steem Ranking
Vote for @Steemitboard as a witness to get one more award and increased upvotes!
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit