apache web server magic on ibm i - event schedule &...
TRANSCRIPT
www.common.org #COMMONS17
Apache Web Server Magic on IBM i
Clark Everetts / Alan Seiden
#COMMONS17www.common.org
Don’t Forget Your Session Surveys
• Sign in to the Online Session Guide (www.common.org/sessions)
• Go to your personal schedule and click on this session
• https://commons17.sched.com/event/9CDx/15cn-apache-web-server-magic-on-ibm-i
• Click on the Feedback Survey button located above the abstract
Completing session surveys helps us plan future programming and provides feedback used in speaker awards. Thank you for your participation.
#COMMONS17www.common.org
• Alan Seiden Consulting - alanseiden.com
• Rogue Wave Software - roguewave.com / zend.com
#COMMONS17www.common.org
• Consultants to innovative IBM i and PHP users
• Alan• PHP project leader, Zend/IBM Toolkit• Contributor, Zend Framework DB2 enhancements• Award-winning developer• Authority, web performance on IBM i
• Clark• 12 years Zend Certified PHP and Zend Framework• Contributor to Zend Framework (mostly IBM i fixes)• Contributor to Zend PHP Toolkit, Zend Server Patterns• Mike Pavlak’s Protégé
PHP on IBM i focus
#COMMONS17www.common.org
Contact Information
Alan Seiden
201-447-2437
alanseiden.com
Twitter: @alanseiden
Clark Everetts
931-434-2326
roguewave.com
zend.com
Twitter: @clarkphp
#COMMONS17www.common.org
What can Apache “serve?”
• Web sites and applications• Allows limited access via TCP/IP requests
• APIs, web services
• Any kind of file
• Static or dynamic data
7
#COMMONS17www.common.org
Apache can be extended via modules
#COMMONS17www.common.org
Requirements & Prerequisites
#COMMONS17www.common.org
Ensure that LICPGM is installed
#COMMONS17www.common.org
http://www-1.ibm.com/support/knowlegecenter/ssw_ibm_i_72/rzaq9/rzap91pp5770dg1wrapper.htm
#COMMONS17www.common.org
Using Navigator for i
#COMMONS17www.common.org
Minimum Software Requirements
• Extended base directory support • 5770-SS1 Option 3
• Host Servers• 5770-SS1 Option 12
• Qshell• 5770-SS1 Option 30
• IBM Portable Applications Solutions Environment for i• 5770-SS1 Option 33
• IBM TCP/IP Connectivity Utilities for i• 5770-TC1
• IBM Developer Kit for Java• 5770-JV1 Option 11
http://www-01.ibm.com/support/knowledgecenter/ssw_ibm_i_72/rzaie/rzaieinstallingprereq.htm
#COMMONS17www.common.org
Permissions for Administrators
• *IOSYSCFG Special Authority
• *CHANGE Authority to the library object QUSRSYS
• *ALL authority to the following objects:• QUSRSYS/QATMHINSTA
• QUSRSYS/QATMHINSTC
• Tip: QATMHINSTC is where the instance really “goes”
• *USE authority for these command objects:• STRTCPSVR, ENDTCPSVR
• *RX authority for:• root (/)
• /www
• *RWX authority for directory “/www/server_name/“
#COMMONS17www.common.org
Let’s create a web server instance
#COMMONS17www.common.org
Using Navigator for i web administrator
Redirects to secure port 2005
Start at port 2001
#COMMONS17www.common.org
Find HTTP and DCM tasks
#COMMONS17www.common.org
Choose web administration
#COMMONS17www.common.org
Web admin menu
#COMMONS17www.common.org
Create new HTTP server
2
0
#COMMONS17www.common.org
Proceed with the wizard
#COMMONS17www.common.org
Finish
Hit green start button
#COMMONS17www.common.org
It works!
Go to http://i.yourserver.comUse actual IP or domain nameSample HTML page will appear
#COMMONS17www.common.org
If it didn’t work: debug tips
DSPMSG QSYSOPR will show error message and job number
Check error log in QTMHHTTP’s spool files:WRKSPLF SELECT(QTMHHTTP)
Common reason for failure: IP/port already allocated
#COMMONS17www.common.org
Detailed troubleshooting
•DSPMSG QSYSOPR
•find startup error ("HTTP Server instance ZENDSVR6 start up failed.")
1
• Put cursor on message
• press F1 to see details2
• Within detailed message, look for job info (something like 108846/QTMHHTTP/ZENDSVR6)3
Copy that info (108846/QTMHHTTP/ZENDSVR6) to your clipboard4
WRKJOB [the job info]5Type "4" to see spool files, the job log of dead job6
• Type "B" to go to the bottom. Then scroll back up till you see a "40" level error.7
#COMMONS17www.common.org
See Active Connections
#COMMONS17www.common.org
Green screen method: NETSTAT
NETSTAT *CNNis the shortcut
#COMMONS17www.common.org
F14 – port #’s
F13 – sort order
Choose “local port”
#COMMONS17www.common.org
F15 – subset
5 – display
Narrow down the list of ports
#COMMONS17www.common.org
Status of the connection
#COMMONS17www.common.org
Jobs using the connection
#COMMONS17www.common.org
Navigator for i method
#COMMONS17www.common.org
#COMMONS17www.common.org
#COMMONS17www.common.org
#COMMONS17www.common.org
#COMMONS17www.common.org
Configure it!
#COMMONS17www.common.org
Modifying Configuration Directives
• Change listener ports
• Restricting access
• Define multiple-domain Virtual Hosts
• Enable load balancing
• Other security suggestions
• More . . .
https://www.ibm.com/support/knowledgecenter/en/ssw_ibm_i_73/rzas1/rzas1directivefinder.htmIBM i HTTP Server Directive Finder
https://httpd.apache.org/docs/2.4/mod/Apache site Module Listing
Apache site Directive Indexhttp://httpd.apache.org/docs/2.4/mod/directives.html
#COMMONS17www.common.org
Editor built into the admin GUI
#COMMONS17www.common.org
Other ways to edit
• GUI editor is “safest” (no CCSID issues), but…
• Edit as you would any IFS file
• Configuration file• /www/yourserver/conf/httpd.conf
• Connect to IFS via:• Notepad++
• Zend Studio or similar editor, and copy/paste/edit from there
• Edit on your PC and transfer with FTP/SFTP/SSH program (e.g. Filezilla) or IBM i Navigator
#COMMONS17www.common.org
Restart to test any configuration change
Restart
#COMMONS17www.common.org
Setup or Change Listeners/Ports
http://httpd.apache.org/docs/2.4/mod/mpm_common.html#listen
# Apache Default server configuration
# General setup directivesListen *:80
Listen 192.170.2.1:80
Allow requests to IP address 192.170.2.1 through port 80
Allow SSL connections to port 8443 as well [Alan]
Listen 192.170.2.1:80Listen *:8443 https
#COMMONS17www.common.org
Multiple “servers” in one configuration
http://www-01.ibm.com/support/knowledgecenter/ssw_ibm_i_72/rzaiemod_vhost_alias.htm?lang=en
# Note: NameVirtualHost directive has no effect since i 7.2
NameVirtualHost 111.22.33.44
<VirtualHost 111.22.33.44>
ServerName www.domain1.com
DocumentRoot /www/domain1
</VirtualHost>
<VirtualHost 111.22.33.44>
ServerName www.domain2.com
ServerAlias domain2.com *.domain2.com
DocumentRoot /www/domain2
</VirtualHost>
This example will provide two virtual host configurations under the same web server instance
#COMMONS17www.common.org
Security Tips
#COMMONS17www.common.org
Reverse Proxy in front
Benefits:
• Extra layer of protection• Don’t reveal the real server’s address
• Give your real server a private address
• Access from inside only
• Provide a “united front” to multiple web servers• A single web site can pull from many other sites, transparently
• A way to add features (e.g. SSL) to web servers when you can’t control them directly
• Caching and content manipulation• Some are optimized for this (e.g. Varnish)
Reverse Proxy
A “front door” that
transparently pulls content
from another server (i.e.
your real server).
#COMMONS17www.common.org
Options for reverse proxy
• Appliance • Runs in your network
• http://bluecoat.com is a popular one
• Cloud-based• http://cloudflare.com
• Includes CDN, optimizer, more
• Your own IBM i partition in the DMZ• Easy to administer
• Separate server (e.g. Linux) if you have the skills
#COMMONS17www.common.org
IBM i reverse proxy configurationLoadModule proxy_module /QSYS.LIB/QHTTPSVR.LIB/QZSRCORE.SRVPGM
LoadModule proxy_ftp_module /QSYS.LIB/QHTTPSVR.LIB/QZSRCORE.SRVPGM
LoadModule proxy_http_module /QSYS.LIB/QHTTPSVR.LIB/ZSRCORE.SRVPGM
LoadModule proxy_connect_module /QSYS.LIB/QHTTPSVR.LIB/QZSRCORE.SRVPGM
# URL path /prod/ will pull content from server .200
<Location /prod/>ProxyPass http://192.168.0.200/
ProxyPassReverse http://192.168.0.200/
</Location>
# URL path /test/ will pull content from server .201
<Location /test/>ProxyPass http://192.168.0.201/
ProxyPassReverse http://192.168.0.201/
</Location>
#COMMONS17www.common.org
Restrict access to particular IP addresses (v2.2)
http://httpd.apache.org/docs/2.2/mod/mod_authz_host.html#allow
http://httpd.apache.org/docs/2.2/mod/mod_authz_host.html#deny
Allow from ibm.comAllow from 10.0Allow from 192.168
Directive Syntax: Allow from all|host|env=[!]env-variable [host|env=[!]env-variable] …
Deny from all
Directive Syntax: Deny from all|host|env=[!]env-variable [host|env=[!]env-variable] …
#COMMONS17www.common.org
Restrict access to particular IP addresses (v2.4)
http://httpd.apache.org/docs/2.4/mod/mod_authz_core.html#require
https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_73/rzaie/rzaiemod_authz_core.htm#require
Require host ibm.comRequire ip 10.0Require ip 192.168
Require all denied
Please note: Mixing 2.2 and 2.4 style directives can lead to unexpected results! Use upgrade Guide:
https://httpd.apache.org/docs/trunk/upgrading.html
Directive Syntax: Require [not] entity-name [entity-name] . . .
#COMMONS17www.common.org
Restricting…continued (v2.2)
http://httpd.apache.org/docs/2.2/mod.mod_authz_host.html
<Directory /www/yourserver/htdocs>Order Deny, AllowDeny from allAllow from ibm.comAllow from 10.0Allow from 192.168
</Directory>
This example will allow access to the docroot folder only from connections originating from ibm.com subdomains and from addresses matching 10.0.*.* or 192.168.*.*
#COMMONS17www.common.org
Restricting…continued (v2.4)
http://httpd.apache.org/docs/2.4/mod.mod_authz_host.htmlhttps://httpd.apache.org/docs/2.4/howto/access.html
<Directory /www/yourserver/htdocs>Require host ibm.comRequire ip 10.0 192.168
</Directory>
This example will allow access to the docroot folder only from connections originating from ibm.com subdomains and from addresses matching 10.0.*.* or 192.168.*.*
#COMMONS17www.common.org
Set permissions on directoriesSecure programmer and QTMHHTTP access after making changes or creating instances.
QTMHHTTP is default web server user
WRKLNK with option 9 or these commands
CHGAUT OBJ(‘/www/yourserver‘) USER(JANPGMR) DTAAUT(*RX) OBJAUT(*NONE)
SUBTREE(*ALL)
CHGAUT OBJ(‘/www/yourserver/htdocs‘) USER(JANPGMR) DTAAUT(*RWX) OBJAUT(*NONE)
SUBTREE(*ALL)
CHGAUT OBJ(‘/www/yourserver/htdocs‘) USER(QTMHHTTP) DTAAUT(*RX) OBJAUT(*NONE) SUBTREE(*ALL)
#COMMONS17www.common.org
Other security suggestions
http://httpd.apache.org/docs/2.4/mod/core.html#servertokens
https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_73/rzaie/rzaiemod_core.htm#servertokens
http:httpd.apache.org/docs/2.4/mod/mod_authz_host.html
https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_73/rzaie/rzaiemod_authz_host.htm
Do not divulge information about the server’s operating system or Apache version
ServerTokens Prod
Do not show directory index page
<Directory /www/yourwebsite>Options -IndexesOrder Allow, DenyAllow from all
</Directory>
#COMMONS17www.common.org
Enable Secure Sockets Layer (SSL)
#COMMONS17www.common.org
Types of domain certificates
5
5
Single domain certificateMultiple domain certificateWildcard certificate (i.e. *.yourserver.com)
Standard (verifies business identity and domain ownership)Extended Validation (additional level of verification)Encryption (128 or 256 bit/SHA-1 or SHA-2)
#COMMONS17www.common.org
Enable SSL
#COMMONS17www.common.org
#COMMONS17www.common.org
Digital Certificate Manager (DCM)
#COMMONS17www.common.org
Go into *SYSTEM certificate store
#COMMONS17www.common.org
We want a Server certificate
#COMMONS17www.common.org
Create “certificate signing request” (CSR)
Specify:Minimum 2048 bitsExact “Common name”
#COMMONS17www.common.org
Submit CSR to a CA vendor
many more...
#COMMONS17www.common.org
CA vendor’s formFollow the steps required by the Certificate Provider. Be prepared to provide account information including:organization detailscontact names and informationpayment informationdomain specific details.
In most cases a representative of the certificate issuer will be contacting and verifying information provided to assert the authenticity of the request for the domain being requested.
#COMMONS17www.common.org
Save certs to IFS on IBM i
Certificate Factory Magic
●Certificate (Your Certificate)
● Intermediate Certificate 1 **
● Intermediate Certificate 2 **
●Root CA Certificate ***
** You may need to download this certificate from the certificate provider*** Root CA certificate may already exist
#COMMONS17www.common.org
Root Certificates may already be included in the store
#COMMONS17www.common.org
Import root and intermediate certificates
Provide paths of CA certs you had copied to IFS..
#COMMONS17www.common.org
Import your “server” certificate
#COMMONS17www.common.org
Assign cert to “applications”With the certificate imported into the store now its time to assign it to the applications that will use it.
Select your new certificate from the list provided
NOTE
Only applications already
defined to use SSL will be
shown on the list. Once you
enable security for a Web
Server instance it is then
added to the application list
showing the servers available
for certificate assignment.
#COMMONS17www.common.org
Success!
Restart Web Servers to activate new SSL certificate..
Almost there…
Restart
#COMMONS17www.common.org
Optional: combine virtual host with SSL
# specify IP address the server is running on
<VirtualHost xx.xx.xx.xx:443>
# server application name set up earlier
SSLAppName QIBM_HTTP_SERVER_DEFAULT
SSLEngine On
SSLCacheDisable
</VirtualHost>
Listen xx.xx.xx.xx:443
NameVirtualHost xx.xx.xx.xx:443
#COMMONS17www.common.org
It works!
• How to tell if SSL is working• Try in a browser; page should appear
• “Lock” icon appears
• Click the “lock” for more information
#COMMONS17www.common.org
URL Magic
#COMMONS17www.common.org
“Rewrite rules”
• Why change a URL?
• Use “friendly” URLs
• Replace /cgi-bin/lansaweb?PROCFUN+JOKPUBW+JOKPW03+DEVwith /literature/request
• Use consistent URLs
• ‘www.’ vs. no www
• Redirect to another URL
#COMMONS17www.common.org
Alan changed his mind on a URL name
• Original name too long, but was already widely referenced• /articles-and-publications-by-alan-seiden
• Wanted to shorten it• /articles-and-publications
• …but not “break” the site for anyone
• RewriteRule to the rescue!• Both URLs point to the same place now
# Map old directory to new
RewriteRule ^articles-and-publications-by-alan-seiden(/)?$ /articles-and-publications/ [R=301,L]
#COMMONS17www.common.org
Search engine optimization trick• Some people type ‘www.’ Some omit it.
• Some web sites will link to Alan with ‘www’ and some not:• www.alanseiden.com, alanseiden.com
• You want search engine credit combined as one site, not split as two. Two dilutes the credibility of your site to search engines.
# Example used on alanseiden.com
# Google and browsers will see ‘www’ site as the definitive address.
# R=301: permanent redirect
RewriteCond %{HTTP_HOST} ^alanseiden.com
RewriteRule (.*) http://www.alanseiden.com/$1 [R=301,L]
#COMMONS17www.common.org
Redirect to https (SSL)# non-SSL
Listen 192.168.5.22:80
<VirtualHost 192.168.5.22:80>
# redirect to HTTPS
RewriteEngine On
RewriteRule ^/(.*) https://%{HTTP_HOST}/$1 [NC,R,L]
</VirtualHost>
# SSL
Listen 192.168.5.22:443
<VirtualHost 192.168.5.22:443>
SSLEngine On
# whatever “application name” you defined
SSLAppName QIBM_HTTP_SERVER_DEFAULT
SetEnv HTTPS_PORT 443
DocumentRoot /www/yourserver/htdocs
<Directory /www/yourserver/htdocs>
Allow from all
</Directory>
</VirtualHost>
#COMMONS17www.common.org
Hide your underyling technology• Which do you prefer?
• /cgi-bin/lansaweb?PROCFUN+JOKPUBW+JOKPW03+DEV
or
• /literature/request
• Show “friendly” URLs that call your programs• https://i.yourserver.com/literature/request
#Map a “friendly” URL to another internal address (in this case, LANSA for the web)
RewriteRule ^/literature/request$
/cgi-bin/lansaweb?PROCFUN+JOKPUBW+JOKPW03+DEV [PT,L]
#COMMONS17www.common.org
Let your imagination run free
• Rewrite rules are powerful and can be complex• http://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewriterule
• https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_73/rzaie/rzaiemod_rewrite.htm#rewriterule
• They use Regular Expressions
• Experiment here:
• www.myregextester.com
• Regular expression tester
#COMMONS17www.common.org
Performance
#COMMONS17www.common.org
Request-response protocol
• Client (browser) requests a file; server responds
• One file at a time (at most 2–6 in parallel)
• Browser requests HTML file, then as it parses HTML, finds other file names to request (images, css, js...)
#COMMONS17www.common.org
Requests can be “blocking” in browser• Browsers typically limit themselves to 2–6 parallel
requests to a given server
• File requests stack up, blocked by prev. requests
• Above, even “304 not modified” files caused blocking
• Solution: reduce number of images or improve caching via “Expires” headers
• http://httpd.apache.org/docs/2.4/mod/mod_expires.html
#COMMONS17www.common.org
Example: “Expires” headers (caching)
• For aggressive caching, place these directives in Apache config file
• Can specify file types:ExpiresActive On
# A2592000 means expire after a month in the client's cache
ExpiresByType text/css A2592000
ExpiresByType application/x-javascript A2592000
ExpiresByType application/javascript A2592000
ExpiresByType text/html A2592000
ExpiresByType image/png A2592000
ExpiresByType image/gif A2592000
ExpiresByType image/jpeg A2592000
• Many options: • http://httpd.apache.org/docs/2.4/mod/mod_expires.html
#COMMONS17www.common.org
More ways to reduce “blocking”
• If many .js or .css files are used:
• Combine them into fewer files
• Move contents of smaller .js or .css files inline to your pages, eliminating those external files
• Google PageSpeed tool will help you decide
• https://developers.google.com/speed/pagespeed/
#COMMONS17www.common.org
Create a favicon for your site
• Browsers always look for a file called favicon.ico in your document root
• Those little icons that appear in the browser
• Once found, will be “remembered” by browser
• If not found, will be requested every time (and cause 404’s)
• How to create a favicon:• http://www.alanseiden.com/2007/05/25/brand-your-site-with-a-favicon/
#COMMONS17www.common.org
Keep HTTP connections alive
• Enable “KeepAlive” setting in Apache
• The TCP connection will stay open, waiting for you
• Good when downloading many images, css, js files
• You’ll reduce the number of three-way “handshakes” that establish a connection
• Even more important with longer SSL handshakes
#COMMONS17www.common.org
KeepAlive details
• Configurable by number of seconds, number of requests (usually this is number of files to be downloaded), before closing the connection.
• Recommended settings for average site• KeepAlive On
• KeepAliveTimeout 15
• Details:• http://httpd.apache.org/docs/2.4/mod/core.html#keepalive
• https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_72/rzaie/rzaiemod_core.htm#keepalive
• Don’t overdo it—you are locking out other users from that HTTP job while it’s dedicated to you
#COMMONS17www.common.org
Connecting takes time
“Connection: close”, “Connecting”
3.6 seconds “Connecting” (longer than average but it really
happened)
Clues that Keepalive is off..
#COMMONS17www.common.org
Firebug’s “Net” tab shows “Connection: Keep-Alive”, and, here, timeout=300
seconds (5 minutes)
Zero seconds to connectKeep-alive is working!
What you see when Keep-alive is on
#COMMONS17www.common.org
Each request passes through several
layers
#COMMONS17www.common.org
Compression reduces file size
• Called gzip or mod_deflate, the same for our purposes
• Compresses, speeds up HTML, JavaScript, CSS, favicons, anything text-based
#COMMONS17www.common.org
Netflix improved with gzip/deflate
• Saw 13-25% performance improvement
• Cut outbound traffic in half• That saves money for a busy site such as Netflix
• Details:• http://www.slideshare.net/billwscott/improving-netflix-performance-experience
• It really works!
#COMMONS17www.common.org
Alan’s compression test
• http://your-server:10088/Samples/SQL_access/DB2_SQL_example.php
• Before compression: 31.0kb; loaded in 250ms
• After compression: 4.4kb; loaded in 109ms.
• That’s 14% of the size and 50% of the time!
#COMMONS17www.common.org
Details of deflate/gzip compression
• Apache directives (sample)
# Load IBM i's module that performs compression
LoadModule deflate_module/QSYS.LIB/QHTTPSVR.LIB/QZSRCORE.SRVPGM
# Specify content types to compress
AddOutputFilterByType DEFLATE application/x-httpd-phpapplication/json text/css application/x-javascriptapplication/javascript text/html
• Tutorial on Alan’s blog:• http://www.alanseiden.com/2010/08/13/maximize-zend-server-
performance-with-apache-compression/
• Apache reference:• http://httpd.apache.org/docs/2.4/mod/mod_deflate.html
#COMMONS17www.common.org
Maximum simultaneous HTTP requests
• Set “ThreadsPerChild” in httpd.conf
• Default: ThreadsPerChild 40 Increase to number of expected HTTP connections
• References
• 7.1
• 7.2
• 7.3
https://www.ibm.com/support/knowledgecenter/en/ssw_ibm_i_73/rzaie/rzaiemod_core.htm#threadsperchild
#COMMONS17www.common.org
Load Balancer
#COMMONS17www.common.org
Apache as load balancer• Variation on reverse proxy shown earlier
• Send requests to multiple servers
• Round-robin
• Ignore “dead” servers
• Scaling an application: a single server can “farm out” requests to other servers
• High availability
Details:7.1 http://www01.ibm.com/support/knowledgecenter/ssw_ibm_i_71/rzaie/rzaiemo
d_proxy_balancer.htm
7.2https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_72/rzaie/rzaiemod_proxy_balancer.htm
7.3https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_73/rzaie/rzaiemod_proxy_balancer.htm
#COMMONS17www.common.org
Load balancer configuration
# All requests (/ root) will be handled by balancer
ProxyPass / balancer://mycluster/ stickysession=PHPSESSIONID nofailover=Off
# Balancer definition
<Proxy balancer://mycluster>
BalancerMember http://127.0.0.1:185
BalancerMember http://127.0.0.1:186 smax=10
# Less powerful server. Don’t send as many requests there
BalancerMember http://1.2.3.6:8009 smax=1 loadfactor=20
</Proxy>
#COMMONS17www.common.org
Apache is your site’s front door
• Make it look nice and clean
• Ensure that it is locked!
• Dropping the “door” metaphor, you can also…• Improve performance by knowing the directives to use
• Improve search engine optimization
• Improve ease of use
• Offer APIs securely
• Share your Apache or other web server stories or questions
#COMMONS17www.common.org
Questions & Avoidance
#COMMONS17www.common.org
Contact
Alan Seiden
Alan Seiden ConsultingHo-Ho-Kus, NJ
[email protected]: @alanseiden
More Free PHP tips:http://devzone.zend.com/
Clark Everetts
Rogue Wave Software / ZendA small town in TN!
[email protected]: @clarkphp
Free PHP tips:http://alanseiden.com/tips
#COMMONS17www.common.org
Don’t Forget Your Session Surveys
• Sign in to the Online Session Guide (www.common.org/sessions)
• Go to your personal schedule and click on this session
• https://commons17.sched.com/event/9CDx/15cn-apache-web-server-magic-on-ibm-i
• Click on the Feedback Survey button located above the abstract
Completing session surveys helps us plan future programming and provides feedback used in speaker awards. Thank you for your participation.