Running php from command line

This is one of those “I know this is possible, but don’t know how”.

php -r 'echo "hello world";'

Only useful for simple onelines. You’re very likely to be better of putting code in a php file and run that script like:

php ./helloworld.php

Installing PHP7.3 on a Rapsberry Pi

Default rasbian still ships with php7.0 even though that version in not supported any more. We will install the latest php 7.3. But because this is not the default we will need to do a few extra tweaks.

In the file /etc/apt/sources.list.d/10-buster.list add

deb http://mirrordirector.raspbian.org/raspbian/ buster main contrib non-free rpi

After saving create the next file sudo nano /etc/apt/preferences.d/10-buster. With the content:

Package: *
Pin: release n=stretch
Pin-Priority: 900

Package: *
Pin: release n=buster
Pin-Priority: 750

Again save. Make the system aware of this source list with

sudo apt update

Now we are ready to install PHP7 with all it’s modules:

sudo apt install -y -t buster php7.3-fpm php7.3-curl php7.3-gd php7.3-intl php7.3-mbstring php7.3-mysql php7.3-imap php7.3-opcache php7.3-sqlite3 php7.3-xml php7.3-xmlrpc php7.3-zip php-apcu

When done check it with php -v it should show a PHP 7.3.. Now we need to add a few fpm things for nginx to work properly.

sudo nano /etc/php/7.3/fpm/conf.d/90-pi-custom.ini

And add:

cgi.fix_pathinfo=0

upload_max_filesize=64m
post_max_size=64m
max_execution_time=600

Finally reload php

sudo service php7.3-fpm reload

Now PHP is ready to use

Extra

You might want image optimization.
We have installed php-gp for that. But that is not enough.

sudo apt install -y optipng gifsicle libjpeg-progs

Installing Nginx on a Rapsberry Pi

In this step we are going to install a webserver (nginx). For those who are bit familiar with webservers you might wonder why we are not using apache? I myself are far more familiar with Apache but Nginx just has better performance. And on the not so powerful pi that is important.

Install Nxing

Like with php we want a newer version. So again we will use the buster source. It should install 1.14. To install nginx run the command:

sudo apt install -y -t buster nginx

Check the version nginx -v it should be version nginx/1.14. or higher

To test if it works enter the IP address in the browser. You should see this page.

If you see an error most likely IPv6 isn’t supported. Open the nginx config file.

sudo nano /etc/nginx/sites-enabled/default

At the top you should see these lines

    listen 80 default_server;
    listen [::]:80 default_server;

Change them to:

    listen 80 default_server;
    #listen [::]:80 default_server;

Save then restart nginx.

sudo nginx -t && sudo service nginx reload

Then test the page again in the browser.

Setting up a site with php and url

First we will do some global settings open: sudo nano /etc/nginx/conf.d/99-custom.conf
Add the following line, we increase the allowed upload sizes.

client_max_body_size 64M;

Note: for the example I use example.com replace that with the url you want to use. If you don’t have the url setup yet you can add it to you own host file. Or instead of the url use the IP-address of the Pi.

We will create our own vhost files. PS I’ll be using example.com but use whatever you intend to use. Create the vhost file: sudo nano /etc/nginx/sites-enabled/example.com.conf

server {
    listen 80;

    server_name example.com;
    root /var/www/example.com/public_html;

    index index.php index.html;

    location / {
        try_files $uri $uri/ =404;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php7.3-fpm.sock;
        fastcgi_intercept_errors on;
        fastcgi_buffers 16 16k;
        fastcgi_buffer_size 32k;
    }
}

Next create the folders needed. Set the rights of those files and add a test page.

sudo mkdir -p /var/www/example.com/public_html
sudo touch /var/www/example.com/public_html/index.php
sudo chown www-data:www-data /var/www/example.com -R
sudo nginx -t && sudo service nginx reload

In that file add sudo nano /var/www/example.com/public_html/index.php

<?php
phpinfo();

Save and reload the webpage you should see this: phpinfo page if all is setup correctly

Now we have a basic and functioning webserver with php.
For security sake delete the index.php file

sudo rm /var/www/example.com/public_html/index.php 

Permissions.

So far we use sudo for pretty much everything. This is fine.
After the initial setup most of the work has to be done in /var/www/*. These files are owned by the nginx user. This also is normal and fine.
We can change nginx to use the pi user.

That way you can avoid the sudo for every small change.

The big upside is no more sudo and changing owners of files.
The downside is that every file pi can access nginx also can access.
This is a security risk of course.

Use this at own risk. The rest of the guide(s) acts as if you didn’t do this.

Open file sudo nano /etc/php/7.2/fpm/pool.d/zzz-users.conf and add.

user = pi
group = pi
listen.owner = pi
listen.group = pi

And reload php sudo service php7.2-fpm restart

Next open sudo nano /etc/nginx/nginx.conf on line 1 the user to pi
Restart nginx sudo nginx -t && sudo service nginx restart

Last step is really making pi the owner of all webfiles: sudo chown pi:pi /var/www/ -R

Next we will install mysql and configure a database.

Curl output format

A lot of usefull informatoin can be caught using curl. Formating the output can be done with the -w --write-out argument

curl -w 'Home loadtime: %{time_total}\nResponse code: %{http_code}\n' -o /dev/null -s 'https://www.janw.me/'

Output example: Bash output of curl request

This example will show the load time and response code. These 2 values are duable. But If you want more it’s more readable to pass a file.

In file: nano curlformat.txt

    time_namelookup:  %{time_namelookup}\n
       time_connect:  %{time_connect}\n
    time_appconnect:  %{time_appconnect}\n
   time_pretransfer:  %{time_pretransfer}\n
      time_redirect:  %{time_redirect}\n
 time_starttransfer:  %{time_starttransfer}\n
                    ----------\n
         time_total:  %{time_total}\n

Then pass the file to curl:

curl -w "@curl-format.txt" -o /dev/null -s "https://janw.me/"

Bash output of curl format file

A list of all avialable variables are in the man pages

Sources:

RaspberryPi up and running

This guide will help you set up a Raspberry Pi with Rasbian. Ready to do pretty much whatever you want.

What hardware do you need?

  • First off a Raspberry Pi of course, for this tutorial I’m using a Model 2B. A 3B should have the same steps. I just don’t have it. A 3B just cost about as much and is faster and has wifi.
  • Second I have a network cable, even if I had a Pi 3B I would still use the cable, it will cost less power. But of course you need to get the network cable to the right location in the house.
  • a micro SD card, at least class 10 for speed and with 8GB or more. The SD card will serve as the main harddrive for the pi. An micro SD adapter is also needed to install the image on the SD card.
  • A micro USB power source. This can get a bit tricky. Recommended is at least 2A with 5V. A normal smartphone adapter won’t give that. Using less will slow down your raspberry.

Installing Rasbian

First off download Raspbian Jessie Lite from the Raspberry pi website. When It’s done flash the image on the SD card. There is an official guide that explains it better then what I could do.

Flashing the image can take a while. You could set up all the wires and put things in place.

When the writing of the SD card is done. Put a file with the name ssh in the root of the boot partition. If you need wifi place a file named wpa_supplicant.conf also in the boot partition. And add the following:

network={
    ssid="YOUR_SSID_WIFI_NAME"
    psk="YOUR_PASSWORD"
    key_mgmt=WPA-PSK
}

I haven’t tried myself so more information here

Then plug in the SD card and powerup. Check the IP address guide to get the ip-address of the pi. Do wait ~5minutes before actually trying. The raspberry has to setup stuff for the first time. If after 20max you still can’t find an IP. The flashing of the SD card has gone wrong and you’ll have to restart.

Go to your own computer and open the terminal (or Putty for the windows users) Login with the command ssh pi@192.168.*.* Use the IP address you noted before. If it asks if you want to continue choose yes. and use the default password: raspberry Putty agian will work a bit different.

You should see something like this:
raspberry-remote-login

Now you are logged-in remote on the raspberry pi. Time to configure some stuff with the command sudo raspi-config.
On this menu we can configure some basic settings. Let’s change some settings.

  1. Change User Password CHANGE THE PASSWORD. Longer is better and safer
  2. Hostname I advise to change the Hostname so it will be easier to find, I named mine pi-webserver.
  3. Boot options Chose the ‘Console Autologin’ of ‘Console’ option. Don’t choose auto login if someone else might have physical access to the pi. This will disable the desktop so it won’t waste power.
    Wait for Network at Boot Just turn this off to be safe.
  4. Internationalisation Options Here you can change the timezone to your current one. You could change the language of the PI and the keyboard layout if you need to. Keep in mind I will be using English.
  5. Interfacing Options we don’t need this.
  6. Overclock Set this to the highest setting. It won’t hurt and will make the Pi a faster.
  7. Advanced Options Change the Memory split to 16. Because we don’t have a interface we won’t need memory for that. Do Expand Filesystem Because the image is made for a 4GB sd card it will only take about 4GB. This option will make sure all available space is used.

When this is finished the pi might download some language packs. It it doesn’t reboot. you have to do it yourself. sudo reboot

Wait about a minute and login in again like before.

updates

This might take a while but first we are going to update.

sudo apt-get update && sudo apt-get upgrade -y

Now we update all default installed software. If the image is old or hasn’t been updated in a while it might take a long time. The date of the image is in the file name of the downloaded image.
At times It might appear to hang. It Unless it’s stuck on one thing 15 minutes it’s probably fine. Give it an 15 to 30 minutes. Else pull the plug.

When it’s done reboot again just to be sure.

You now have a Raspberry Pi ready for use.

Migrate one site out a multisite.

We where asked to host a site. But then it turned out that site was part of a bigger multisite. So after I got all files & db of the complete site I needed to clean it up and only keep the requested site left.

The quick and dirty steps:

  • Don’t change the DNS until you’re done testing.

Webhosting settings

  • Import all files on the server
  • Import the database and change the db settings in wp-config.php.
  • Locally add the domain to the hosts file So I didn’t need to change urls
  • delete all sites using wp site delete SITE_ID
  • Only keep site 1 (the primary you can’t delete) and site 12 (the site ID I needed)

Rename the tables

  • Rename the site 1 tables in mysql RENAME TABLE `amsterda_db`.`wp_links` TO `amsterda_db`.`wp_BACKUP_links`;
  • Rename the site 12 tables to the normal tables RENAME TABLE `amsterda_db`.`wp_12_links` TO `amsterda_db`.`wp_links`;
  • Make sure you only rename the site tables, don’t rename wp_blogs and other multisite tables

Update the url

  • In wp_blogs delete the record of site 12 and change the name to the new main site in wp_blogs.domain. And rename the url inside wp_site.
  • Also cleanup the wp_blog_versions.
  • In wp-config.php change the constant DOMAIN_CURRENT_SITE
  • Search the database for all mentions of the old mainsite. This is a per case check what should be done.
    Links in posts are probably fine. The old url in the wp_options maybe not.

Permissions and roles

  • In the wp_options table search for wp_user_roles as option_name. If this record is not present. Search it in the wp_BACKUP_options and create the record manually.
  • Permissions are still set for site 12 fix that using wp search-replace wp_12_ wp_ wp_usermeta

Test

  • Test your site. At least test uploads, permalinks, creating/updating pages
  • The normal steps usually when deploying a new site.
  • Think about things that might differ on this inherent setup.

Live

  • switch DNS
  • SSL

After the first week

  • Delete all wp_BACKUP_* tables
  • Check for unneeded plugins
  • Check for unneeded users.
  • Possible you should cleanup the uploads folder of old sites, although there may be links to those uploads.

Of course it would be even better to remove the multisite setup. But I was out of time. And I still would have done these steps first.

Posted in TIL

PHP interface type hinting

In interfaces you can force the return type

interface InterfaceTest {
    function GetSingleEntity(): Entity;
    function GetEntitySet() : Entity[];
}

GetEntitySet should return a array containing Entities. But this kind of syntax is not allowed.
You could just change it to only return an array, but the forcing of the class is the most powerful.
The best is to create a wrapper class for the entities, best would be to use an Iterator.

sed command line tool

sed is not new for me. But it’s such a versatile tool. And I always have trouble finding the precice syntax I need. So here is a collection of examples. It probably will grow in the years.

Replace the home dir with ~.

COMPACT=$(echo ${HOME} | sed "s#${HOME}#~#g")

Replace %SALT% with the variable $SALT in the file wp-config.php

sed -i -E "s/%SALT%/$SALT/g"  "wp-config.php"