Python Flask minimal


Create an environment
python3 -m venv venv

Activate the environment
. venv/bin/activate

Deactivate the environment

Install Flask
pip install Flask

# Import the Flask class - an instance of this class
# will be a WSGI application.

from flask import Flask

# Next we create an instance of this class. The first
# argument is the name of the application’s module or
# package. __name__ is a convenient shortcut for this
# that is appropriate for most cases. This is needed so
# that Flask knows where to look for resources such as
# templates and static files.

app = Flask(__name__)

def hello_world():
    return "<p>Hello, World!</p>"

export FLASK_APP=hello
flask run

If debugger disabled or you trust the users on your network, make the server publicly available
flask run --host=

The debugger allows executing arbitrary Python code from the browser. It is protected by a pin, but still represents a major security risk.
export FLASK_ENV=development
flask run


WordPress – unable to create directory

Resolution for ‘Unable to create directory’ error in WordPress.

This error is caused by an inappropriate set of folder and file permissions. The following statements assume you have shell access to the document root of your webserver.

Set owner and group of each folder and file to the webserver user
sudo chown -R www-data:www-data /var/www/html

Set permissions for all folders to 755
sudo find /var/www/html -type d -exec chmod 755 {} \;

Set permissions for all files to 644
sudo find /var/www/html -type f -exec chmod 644 {} \;

For problems uploading images, also check the uploads folder is set appropriately in WordPress Dashboard > Settings > Media. If already set to the default wp-content/uploads, this field may not be visible.



A visual web log analyzer.

Connect to your webserver via ssh and pipe the access log to goaccess running locally. Create a report in html format.

ssh user@ \
'cat /var/log/apache2/' | \
goaccess -a -o /home/chris/report.html --log-format=COMBINED --html-report-title=" logs" -
Developer notes

Homestead Vagrant xdebug3 vscode phpspec

Reset to original state

./vagrant destroy --force && ./vagrant up


    "version": "0.2.0",
    "configurations": [
            "name": "Listen for Xdebug",
            "type": "php",
            "request": "launch",
            "port": 9003,
            "log": true,
            "pathMappings": {
                "/home/vagrant/homestead.test": "/home/chris/code/homestead.test"

Start an ssh session

./vagrant ssh

Create the xdebug log file

sudo touch /var/log/xdebug.log && sudo chmod 777 /var/log/xdebug.log

Create xdebug settings
sudo nano /etc/php/7.4/fpm/conf.d/20-xdebug.ini
xdebug.mode = debug
xdebug.discover_client_host = true
xdebug.client_host =
xdebug.client_port = 9003
xdebug.max_nesting_level = 512

; required for cli debugging but for browser
; could omit and use query string at end
; of url instead XDEBUG_SESSION_START=name
xdebug.start_with_request = yes

; ensure file exists and is writeable
xdebug.log = /var/log/xdebug.log

Switch to cli PHP 7.4


For cli debugging (alias xon=’sudo phpenmod -s cli xdebug’)


After these changes

./vagrant reload --provision

Run phpspec

./vagrant ssh
tail -f /var/log/xdebug.log
project/dir vendor/bin/phpspec run

If vscode will not stop on a breakpoint try re-enabling PHP Debug extension and restarting vscode.

Run ngrok (outside of Homestead) pointing at a configured Homestead site

ngrok http

Selenium with Python

Create a virtual environment

python3 -m venv env

Get gekodriver (for FireFox)

It needs to be in the PATH (using Ubuntu here)

sudo mv geckodriver /usr/local/bin/geckodriver

Activate the virtual environment

source env/bin/activate

Install Selenium

pip install selenium

The script

from selenium import webdriver
from import By
from selenium.webdriver.common.keys import Keys
from import WebDriverWait
from import presence_of_element_located

#This example requires Selenium WebDriver 3.13 or newer
with webdriver.Firefox() as driver:
    wait = WebDriverWait(driver, 10)
    driver.find_element(By.NAME, "q").send_keys("cheese" + Keys.RETURN)
    first_result = wait.until(presence_of_element_located((By.CSS_SELECTOR, "h3")))

Captive portal

When connected to a wifi captive portal and the login screen won’t appear, try any of the following: (from a Chromium browser)

Scaffold Symfony app from existing database

Prepare for a new run

rm -r src/Entity/*
rm -r src/Form/*
rm -r src/Controller/*
rm -r src/Repository/*
rm -r templates/*

Copy in a backup of base twig template

cp base.html.twig templates/

Generate entities from an existing database

bin/console doctrine:mapping:import "App\Entity" annotation --path=src/Entity
bin/console make:entity --regenerate App

Make CRUD for each new entity

bin/console make:crud MyEntity
bin/console make:crud AnotherEntity

Adjust file permissions

sudo chown -R chris:chris templates/
sudo chown -R chris:chris src/Entity/
sudo chown -R chris:chris src/Controller/
sudo chown -R chris:chris src/Form/

Now, sql insert data fixtures

Linux tips

Query DNS data


Query for information on all DNS records

dig ANY

Query for A records

dig A

host, nslookup and dig share similar functionality.


Return information about a domain name registration, including the name servers it is configured to work with

Linux tips

Ubuntu select and paste with Mouse Keys

On Linux I like to make use of the select and paste feature i.e. selecting text copies it and the middle mouse button pastes it. When a laptop touchpad has no buttons a middle mouse click can be simulated with a three-finger tap, but this is awkward.

Here is my workaround (for keyboards with a numeric keypad only):

  1. From the Accessibility menu turn on Mouse Keys.
  2. Ensure the Number Lock is off.
  3. Select text.
  4. Paste text by pressing 5 on the numeric keypad.

Furthermore, in a terminal and some other applications SHIFT + INSERT will paste text which has been previously selected.

I am using Ubuntu 20.04.1 and GNOME 3.36.8


WordPress debugging

To turn on debugging add the following to wp-config.php

// Turn debugging on
define('WP_DEBUG', true);

// Tell WordPress to log everything to /wp-content/debug.log
define('WP_DEBUG_LOG', true);

// Display error messages
define('WP_DEBUG_DISPLAY', true);

Write to /wp-content/debug.log

error_log('logging message here...');