Adding “Cookie: NO_CACHE=1” will make Varnish to pass the request directly to Apache
time curl -I http://example.com/pagetotest -H "Cookie: NO_CACHE=1"
Adding “Cookie: NO_CACHE=1” will make Varnish to pass the request directly to Apache
time curl -I http://example.com/pagetotest -H "Cookie: NO_CACHE=1"
average apache process mem usage
ps -H h -ylC httpd | perl -lane '$s+=$F[7];$i++;END{printf"Avg=%.1fMB\n",$s/$i/1024}'
ps -H h -ylC apache2 | perl -lane '$s+=$F[7];$i++;END{printf"Avg=%.1fMB\n",$s/$i/1024}'
highest process mem usage cd
ps -H h -ylC httpd | awk 'function max(x){i=0;for(val in x){if(i<=x[val]){i=x[val];}}return i;}function min(x){i=max(x);for(val in x){if(i>x[val]){i=x[val];}}return i;}/^#/{next}{a[$8]=$8;next}END{minimum=min(a);maximum=max(a);print "Max = "maximum / 1024 "MB";print "Min = "minimum / 1024"MB"}'
ps -H h -ylC apache2 | awk 'function max(x){i=0;for(val in x){if(i<=x[val]){i=x[val];}}return i;}function min(x){i=max(x);for(val in x){if(i>x[val]){i=x[val];}}return i;}/^#/{next}{a[$8]=$8;next}END{minimum=min(a);maximum=max(a);print "Max = "maximum / 1024 "MB";print "Min = "minimum / 1024"MB"}'
php-fpm – www pool average
for pid in $(ps aux | grep fpm | grep "pool www" | awk '{print $2}'); do pmap -d $pid | tail -1 ; done | sed 's/K//' | awk '{sum+=$4} END {print sum/NR/1024}'
php-fpm – ALL active pools average memory
Ubuntu: cd /etc/php5/fpm/pool.d Centos: cd /etc/php-fpm.d/
for pool in `ls *.conf` ; do POOL="`echo $pool | sed 's/\.conf//'`" ; echo -e "\n$POOL" ; for pid in $(ps aux | grep fpm | grep "pool $POOL" | awk '{print $2}'); do pmap -d $pid | tail -1 ; done | sed 's/K//' | awk '{sum+=$4} END {print sum/NR/1024}' ; done
MANUAL CHECKS (understanding)
# ps aux | grep apache2 (or httpd) USER PID %CPU PerformanceOptimized %MEM VSZ RSS TTY STAT START TIME COMMAND
-> RSS is the real memory value
-> VSZ is the one that it might reach (important mostly for MySQL)
# Quicker way is to do top and than press ‘>’
Get latest version
wget https://files.phpmyadmin.net/phpMyAdmin/4.4.14/phpMyAdmin-4.4.14-all-languages.zip
Unzip in /var/www/pma
Create config file
cp config.sample.inc.php config.inc.php
Create phpmyadmin db
mysql < create_tables.sql
Create user
mysql -e "GRANT SELECT, INSERT, DELETE, UPDATE ON phpmyadmin.* TO 'pmaadmin'@'%' IDENTIFIED BY '<PASS>'"
Enable parts related to the db, username and pw from above
vim config.inc.php
Create configuration file (copy and paste the whole command):
cat > /etc/httpd/conf.d/phpMyAdmin.conf <<EOF Alias /phpMyAdmin /var/www/html/pma Alias /phpmyadmin /var/www/html/pma <Directory /var/www/html/pma/> AuthType Basic AuthName "Restricted" AuthUserFile /etc/phpMyAdmin/.htpasswd Require valid-user </Directory> EOF
Create auth file
htpasswd -c /etc/phpMyAdmin/.htpasswd admin (FYI 'admin' it's the username)
To ADD users, just remove the -c flag
Sample setup for Apache virtual host and PHP-FPM pool with variables instead hard coded user details.
This could be handy if your are scripting your deploy (e.g. with Ansible).
In our example we are using the following:
Domain: example.com
SFTP user: example.com
Document root: /var/www/vhosts/example.com/httpdocs/
<VirtualHost *:80> ServerName example.com ServerAlias www.example.com DocumentRoot /var/www/vhosts/example.com/httpdocs <Directory /var/www/vhosts/example.com/httpdocs> require all granted Options Indexes AllowOverride All </Directory> ErrorLog "logs/example.com-error_log" CustomLog "logs/example.com-access_log" combined env=!forwarded CustomLog "logs/example.com-access_log" proxy env=forwarded # Configure proxy connector <Proxy "unix:/dev/shm/example.com-php5-fpm.sock|fcgi://php-fpm"> # we must declare a parameter in here (doesn't matter which) or it'll not register the proxy ahead of time ProxySet disablereuse=off </Proxy> # # Redirect to the proxy connector <FilesMatch \.php$> SetHandler proxy:fcgi://php-fpm </FilesMatch> <Directory /var/www/vhosts/example.com/httpdocs/wp-content/uploads> # Important for security, prevents someone from # uploading a malicious .htaccess AllowOverride None SetHandler none SetHandler default-handler Options -ExecCGI php_flag engine off RemoveHandler .cgi .php .php3 .php4 .php5 .phtml .pl .py .pyc .pyo <Files *> AllowOverride None SetHandler none SetHandler default-handler Options -ExecCGI php_flag engine off RemoveHandler .cgi .php .php3 .php4 .php5 .phtml .pl .py .pyc .pyo </Files> </Directory> </VirtualHost>
Create a file called example.com.conf in /etc/php-fpm/pool/
[example.com] listen = /dev/shm/$pool-php5-fpm.sock user = $pool group = $pool listen.owner = $pool listen.group = apache listen.mode = 0666 pm = dynamic pm.max_children = 35 pm.start_servers = 5 pm.min_spare_servers = 5 pm.max_spare_servers = 25 slowlog = /var/log/php-fpm/$pool-slow.log php_admin_value[error_log] = /var/log/php-fpm/$pool-error.log php_admin_flag[log_errors] = on php_value[session.save_handler] = files php_value[session.save_path] = /var/lib/php/session/$pool
apt-get install php5-mysql php5-fpm php5-gd php5-cli apache2-mpm-worker libapache2-mod-fastcgi
Create a php-fpm pool /etc/php5/fpm/pool.d/$USER.cnf
[$USER] user = $USER group = www-data listen = 127.0.0.1:9000 listen.owner = www-data listen.group = www-data pm = dynamic pm.max_children = 100 pm.start_servers = 35 pm.min_spare_servers = 15 pm.max_spare_servers = 35 php_value[session.save_handler] = files php_value[session.save_path] = /var/lib/php/session/$USER chdir = /
In Vhost:
ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/var/www/vhosts/MYDOMAIN.COM/public_html/$1
Enable/disable modules and restart services
a2dismod mpm_prefork php5 && a2enmod actions fastcgi alias mpm_event proxy_fcgi proxy service php5-fpm restart service apache2 restart
Don’t forget to enable “index.php” in your DirectoryIndex directive, if using PHP-FPM! Also, remove any PHP directives from Apache, and configure in PHP-FPM instead.
Reset Admin Password
UPDATE wp_users SET user_pass=MD5(‘newpassword123’) WHERE ID = 1;
Create New Admin account
mysql> INSERT INTO `wp_users` (`user_login`, `user_pass`, `user_nicename`, `user_email`, `user_url`, `user_status`, `display_name`) VALUES (‘username’, MD5(‘password’), ‘friendly-name’, ‘[email protected]’, ‘http://example.com’, ‘0’, ‘Your Name’);
mysql> SELECT LAST_INSERT_ID() INTO @userid;INSERT INTO `wp_usermeta` (`umeta_id`, `user_id`, `meta_key`, `meta_value`) VALUES (NULL, @userid, ‘wp_capabilities’, ‘a:1:{s:13:”administrator”;s:1:”1″;}’), (NULL, @userid, ‘wp_user_level’, ’10’);
Show error in case white screen appears
Try adding this line to wp-config.php to see the errors on the page:
define( ‘WP_DEBUG’, true );
Change the site URL
mysql> SELECT * FROM wp_options WHERE option_name = ‘siteurl’ OR option_name = ‘home’ ;
mysql> UPDATE wp_options SET option_value = ‘http://staging.walacea.com’ WHERE option_name = ‘siteurl’ OR option_name = ‘home’ ;
Disable all plugins
mysql> UPDATE wp_options SET option_value = ‘a:0:{}’ WHERE option_name = ‘active_plugins’;
Show users and Privileges
mysql> SELECT user_login,user_registered,meta_value FROM wp_users INNER JOIN wp_usermeta ON wp_users.id = wp_usermeta.user_id and meta_key = ‘wp_capabilities’;
+—————+———————+———————————+
| user_login | user_registered | meta_value |
+—————+———————+———————————+
| administrator | 2013-12-21 10:36:30 | a:1:{s:13:”administrator”;b:1;} |
| author | 2014-11-25 15:50:34 | a:1:{s:6:”author”;b:1;} |
| editor | 2014-11-25 15:51:18 | a:1:{s:6:”editor”;b:1;} |
| contributor | 2014-11-25 15:51:48 | a:1:{s:11:”contributor”;b:1;} |
| subscriber | 2014-11-25 15:52:11 | a:1:{s:10:”subscriber”;b:1;} |
+—————+———————+———————————+
5 rows in set (0.01 sec)
Update theme to Twenty Fourteen
mysql> UPDATE wp_options SET option_value = ‘twentyfourteen’ WHERE option_name = ‘template’ OR option_name = ‘stylesheet’;
mysql> UPDATE wp_options SET option_value = ‘Twenty Fourteen’ WHERE option_name = ‘current_theme’;
Administration Over SSL
Add the below lines to the wp-config.php file above the ‘/* That’s all, stop editing! Happy blogging. */’ line
define(‘FORCE_SSL_ADMIN’, true);
define(‘FORCE_SSL_LOGIN’, true);
This ensures the login AND the administration is done over SSL
—
You could also use the below htaccess:
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /(.*)\ HTTP/ [NC]
RewriteCond %{HTTPS} !=on [NC]
RewriteRule ^/?(wp-admin/|wp-login\.php) https://mysite.com%{REQUEST_URI}%{QUERY_STRING} [R=301,QSA,L]
Find out how many SQL queries are executed every time a page is loaded.
Add the below to one of the theme files, I usually add to footer.php
if ( current_user_can( ‘manage_options’ ) ) {
echo $wpdb->num_queries . ” SQL queries performed.”;
} else {
// Uncomment the below line to show SQL queries to everybody
// echo $wpdb->num_queries . ” SQL queries performed.”;
}
e.g. on my site when I’m logged in…
Here are some configuration parameters you can add to your wp-config.php file for FTP.
define(‘FS_METHOD’, ‘direct’);
/*
forces the filesystem method. It should only be “direct”, “ssh2”, “ftpext”, or “ftpsockets”. Generally, you should only change this if you are experiencing update problems. If you change it and it doesn’t help, change it back/remove it. Under most circumstances, setting it to ‘ftpsockets’ will work if the automatically chosen method does not.
(Primary Preference) “direct” forces it to use Direct File I/O requests from within PHP, this is fraught with opening up security issues on poorly configured hosts, This is chosen automatically when appropriate.
(Secondary Preference) “ssh2” is to force the usage of the SSH PHP Extension if installed
(3rd Preference) “ftpext” is to force the usage of the FTP PHP Extension for FTP Access, and finally
(4th Preference) “ftpsockets” utilises the PHP Sockets Class for FTP Access.
*/
define(‘FTP_BASE’, ‘/var/www/vhosts/example.com/httpdocs/’); // is the full path to the “base”(ABSPATH) folder of the WordPress installation.
define(‘FTP_CONTENT_DIR’, ‘/var/www/vhosts/example.com/httpdocs/wp-content/’); // is the full path to the wp-content folder of the WordPress installation.
define(‘FTP_PLUGIN_DIR ‘, ‘/var/www/vhosts/example.com/httpdocs/plugins/’); // is the full path to the plugins folder of the WordPress installation.
define(‘FTP_PUBKEY’, ‘/var/www/vhosts/example.com/httpdocs/.ssh/id_rsa.pub’); // is the full path to your SSH public key.
define(‘FTP_PRIKEY’, ‘/var/www/vhosts/example.com/httpdocs/.ssh/id_rsa’); // is the full path to your SSH private key.
define(‘FTP_USER’, ‘FTPusername’); // is the FTP username
define(‘FTP_PASS’, ‘FTPpassword’); // is the password for the FTP User
define(‘FTP_HOST’, ‘localhost’); // FTP Host – usually localhost.
define(‘FTP_SSL’, false); // This is for “Secure FTP” not for SFTP.
Compile module:
yum -y install httpd-devel gcc mkdir /home/rack/fastcgi cd /home/rack/fastcgi wget https://github.com/whyneus/magneto-ponies/raw/master/mod_fastcgi-SNAP-0910052141.tar.gz tar -zxf mod_fastcgi* cd mod_fastcgi-* make -f Makefile.AP2 top_dir=/usr/lib64/httpd cp .libs/mod_fastcgi.so /usr/lib64/httpd/modules/
Enable the module:
echo "LoadModule fastcgi_module /usr/lib64/httpd/modules/mod_fastcgi.so" >> /etc/httpd/conf.d/fastcgi.conf
Install php-fpm and create pools like this:
[$USER] listen = /dev/shm/$USER-php5-fpm.sock user = $USER group = $USER listen.owner = $USER listen.group = apache listen.mode = 0666 pm = dynamic pm.max_children = 35 pm.start_servers = 5 pm.min_spare_servers = 5 pm.max_spare_servers = 25 slowlog = /var/log/php-fpm/$USER-slow.log php_admin_value[error_log] = /var/log/php-fpm/$USER-error.log php_admin_flag[log_errors] = on php_value[session.save_handler] = files php_value[session.save_path] = /var/lib/php/session/$USER/
NOTE: Make sure the path /var/lib/php/session/$USER/ exists and its owned by $USER!
Add this in the VHOST configuration (before the end of </VirtualHost>) )
FastCGIExternalServer /dev/shm/$USER-php.fcgi -socket /dev/shm/$USER-php5-fpm.sock -flush -idle-timeout 1800 AddHandler php-fpm .php Action php-fpm /php.fcgi Alias /php.fcgi /dev/shm/$USER-php.fcgi DirectoryIndex index.php <FilesMatch "\.php$"> SetHandler php-fpm </FilesMatch>
Putting PHP session files in a single pool can be done using memcached which has the benefit of being faster to look up and no longer relying on a slow filesystem to save session files to (memcached stores its data in memory) but you need to have your developers check that your code won’t have any issues using this over session files.
Install the package and set the configuration file:
PORT="11211" USER="memcached" MAXCONN="1024" CACHESIZE="128" OPTIONS="-l 127.0.0.1"
Make sure that memcache php plugin is there – or install it
Change this in php.ini
session.save_handler = memcached session.save_path = "tcp://127.0.0.1:11211?persistent=1&weight=1&timeout=1&retry_interval=15"
Check memcache stats
echo "stats" | nc 127.0.0.1 11211 echo "stats" | nc -w 1 127.0.0.1 11211 | awk '$2 == "bytes" { print $2" "$3 }'
Install iptables and remove firewalld
yum install -y iptables-services systemctl stop firewalld systemctl mask firewalld systemctl enable iptables systemctl start iptables
git clone https://github.com/letsencrypt/letsencrypt cd letsencrypt ./letsencrypt-auto
If this command doesn’t work, you can try the following manual way
./letsencrypt-auto certonly --email [email protected] --webroot -w /var/www/vhosts/yourdomain.com -d yourdomain.com -d www.yourdomain.com
You can add multiple domains under the same certificate
./letsencrypt-auto certonly --email [email protected] --webroot -w /var/www/vhosts/yourdomain.com -d yourdomain.com -d www.yourdomain.com -w /var/www/vhosts/yourdomain2.com -d yourdomain2.com -d www.yourdomain2.com
Update your Apache configuration to use the new certificate:
SSLEngine on SSLCertificateKeyFile /etc/letsencrypt/live/yourdomain.com/privkey.pem SSLCertificateFile /etc/letsencrypt/live/yourdomain.com/cert.pem SSLCertificateChainFile /etc/letsencrypt/live/yourdomain.com/chain.pem
Check domain:
https://crt.sh/?q=%25yourdomain.com
Renew the certificate with a script set in a cron (set every 2 months – certificate expires every 3)
# run on the 1st of Odd Months at midnight | Renew certificates 0 0 1 1-11/2 * root /root/letsencrypt/renew.sh >/dev/null 2>&1
renew.sh script:
#!/bin/bash [email protected] LOG=/var/log/letsencrypt/renew.log SENDMAIL=/usr/sbin/sendmail CMD="renew" /root/letsencrypt/letsencrypt-auto $CMD > $LOG 2>&1 if [ $? -eq 0 ] ; then service httpd graceful else echo -e "Subject: [letsencrypt] SSL automatic renewal FAILED\n$(cat $LOG)" | $SENDMAIL $MAIL exit 1 fi
Sources:
https://letsencrypt.org/getting-started/
https://www.a2hosting.com/kb/security/ssl/securing-your-site-with-a-lets-encrypt-ssl-certificate