Connection a Psion Series 3a to my Mac

I follow James Weiner on Mastodon (@hypertalking@bitbang.social) because of his beautiful one-pixel art and his work on restoring old computers. Last week he boosted a post which mentioned Psion PDA’s which lead me down a rabbit hole which ended at Psion User Group which is maintained by Alex Brown (@thelastpsion@bitbang.social). I remembered still having a Psion Series 3a myself somewhere stowed away in a closet together with a Palm V and a Tungsten T3.
Psion series 3a

The journey got me thinking if would be possible to use the Psion, which still looks like a great device, in a current setup and have it sync data with my Mac Studio. This send me down another journey searching for accurate documentation but I found that lacking. It was mostly for Windows based computers (32 bit and not working on most 64 bit machines) and for Apple which was a bit more obscure at that time even less. If there was anything for MacOSX it was for Intel based machines and definitely not for Apple Silicon.

Toady I got the connectivity working with the excellent help of Alex Brown and Chris Farrow on the Psion User Discord server. I thought I’d write down the steps how I got it working as a reference for others who might want to follow me down this rabbit hole as well.

First problem is the physical connection, it based on sub D9 connector or more commonly known as a serial port. Your Psion series 3a came with a special cable called the 3 Link which was a serial connection interface.
Psion 3 Link The problem being that current computer hardware does not have any serial or even parallel connectors that where once ubiquitous. To resolve this I had to buy an USB to Serial interface which was obtained via Amazon. You can use others but they must have the PL2303 chip takes care of the proper communication.

Next you’ll have to install the driver which was to my surprise available in the App Store PL2303 Serial. The next step is optional but I found it very useful to test if there is any connectivity between the Mac and the Psion and the cable is doing it’s thing. You’ll use a Terminal emulator to connect both devices. I’ve used SerialTools on my Mac because it’s free and available in the App Store. On the Psion you’ll need to install the Comm tool, if it not installed then you can use Psion-I, select the C: drive, and install Comms.app. (before you do, make sure you disabled the 3-Link).

Open the Comms tool on your Psion and on the Mac you open Serialtools, select the PL2303 port, set baud rate to 9600 and press connect. What you type on the Mac should appear on the Psion screen and vice versa. This proves a proper connection between your Psion Series 3a and your Mac.

There are several options for the next fase, installing plptools, running a windows VM to use the PsiWin program or use DosBox staging to run Mclink

I have chosen to start with the DosBox option as it was the simplest option to get started. I dabbled with the plptools option but I haven’t got it working yet. So here are my instructions on using the DosBox option.

First you need to download the Mclink program from here, unzip it in a separate directory which you will reference later.

Download the latest version of DosBox staging from their download page and install the program. When installed, first start the application and on the new Z:\> prompt type the command: config -wc to create a new config file in ~/Library/Preferences/DOSBox called dosbox-staging.conf.You’ll need to edit this to make a link to your new serial connection. Mine was located at /dev/tty.PL2303G-USBtoUART8340 check using the Terminal if your is called the same. Find the line that starts with serial1 and make it look like: serial1 = direct realport:tty.PL2303G-USBtoUART8340.

At the end of the file you can add commands that can be executed during startup. The command I added is the mounting of the directory where I extracted my copy of Mclink. mount c /directory/location/of/mclink

To use the new configuration file you’ll need to restart the DosBox program. After it’s restarted you can issue the command c:\mclink when the mclink program has started you should see a screen like: mclink init screen Next connect your Psion Series 3a using your new USB to serial cable with the 3link cable. Start the 3-Link program by pressing Psion-L (Key combination, bottom left key and the L together) and turn it on at 19200 baud. If everything is correct you’ll see mclink connecting and three lines should appear at the top of the window like: mclink connected screen As you can see I’ve asked for the directory contents of the ramdisk of the Psion using the command: dir rem::m:\* for more commands on how to exchange information please locate the MCLINK.DOC file which explains all of them. Have fun!

Dump and backup a database on shutdown

I’m using Multipass as the virtualisation tool for quickly setting up virtual development machines on my Mac Studio using cloud-init for configuration and setting everything up. This really works great and has saved me several times where stuff crashed and burned, it was really easy just to tear everything down and re-run the setup scripts. (You can read more on my setup in the repository I use for this. This works fine as my development stuff is mostly in stored in Git and the data in a shared MySQL virtual server but as I recently found out this is not lways the case. Sometimes there is local data on the virtual server that you would like to keep.

The solution I came up with to prevent the loss of data is to trigger a script on the shutdown of the server that would copy the relevant data to a safe location. In my case that would be an S3 bucket. I took some digging, searching and testing but I got it working. So if you are looking for something similar, here how I did it:

We use a system service that runs at the start of the shutdown proces, so that other services that we rely on are still running. I’ve named it my S3shutdown.service which is the name of a file which you need to create in /etc/systemd/system/ with the follwing content:

[Unit]
Description=Save database to S3
Before=shutdown.target reboot.target halt.target

[Service]
Type=oneshot
RemainAfterExit=true
ExecStop=/home/ubuntu/projects/dumpandstore.sh

[Install]
WantedBy=multi-user.target

Where the first line is a descriptive title which you will see used in syslog when it is executed. The last line defines the runtime, so before the multi user mode ends. Referenced by ExecStop you reference the shell script that should be run at the moment the server is going down.

My dumpandstore.sh script looks like:

#! /bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

/usr/bin/mysqldump -uuser -ppassword databasename > /home/ubuntu/projects/databasedump.sql;
today=$(date +%Y%m%d);
cp /home/ubuntu/projects/databasedump.sql.sql /home/ubuntu/projects//databasedump$today.sql
/usr/bin/gzip /home/ubuntu/projects//databasedump.sql$today.sql

/usr/local/bin/aws s3 cp  /home/ubuntu/projects/databasedump.sql$today.sql.gz s3://mybucketname/
/usr/local/bin/aws s3 cp  /home/ubuntu/projects/databasedump.sql s3://mybucketname/

I’ve used a dump with a data to build some historic perspective, the other file without data is so to speak the last copy and is also referenced in the build script of the server. So that when I rebuild the server the database is filled with the last used dataset.

To activate the service you’ll need to run the command: sudo systemctl enable S3shutdown.service Reboot the machine and everything should be working as intended. Some problem struggled with was the aws comfiguration. I had setup the aws configuration including credentials as a normal user but the shutdown service runs as root and therefore the aws command cloud not locate the proper credentials. This was quicky solved by copying the ~/.aws directory to /root Not ideal but it made it work for the moment, I need to do more research for a more elegant and safer solution.

The command line is the future of interaction

Yesterday I read this blog post from Lukas Mathis. It kept resonating with me as I recognised some of the scenarios and could even come up with some more. As an avid Apple user and forced to work on a Windows based platform I regularly need to google for instructions on how to perform certain tasks. I want to make a special mention to the Microsoft Office suite where the menu structure is unintuitive with an inconsistent toolbar where I also end up using the Help function a lot to find the right option.

This could mean a big change in UI design moving away from WIMP, touch interfacing and could be the precursor to voice interaction with the desktop. This is already possible especially on a Mac with Accessibility options enabled. But for that to happen in a common setting we first need to enable sub vocal interaction. It is socially awkward to talk to your mobile or computer in a public space and can you visualise an office space with everybody talking to their computer, very noisy. I recently saw this post which means that it won’t take long before we see a practical solution to this.

Looking forward to this…

Deploying Hugo site using Bitbucket pipelines

I have a spare Mac mini running which has all sorts of projects running on it. One of them had a hook into a git repository of a Hugo website which would build it once I committed it to the master and coopy it over to my webserver. It was tedious and sometimes it broke, last week I had enoughof it and looked for a solution that is stable and has less maintenace. The solution I ended up with are the Bitbucket Pipelines

The setup in the end was quite easy, I only had to gather the required examples, configuration and settings from several diffent places. So for prosperity and for other people in the same situation I’m describing my solution here.

First in bitbucket you have to login and go to the repository where you store your Hugo website (source and such) then on the left and bottom go to “Repository settings” in the new itemlist go to the bottom en select “Settings” where you can “Enable Pipelines”.

Then goto “Repository variables” where you can define variables that can be used in your later scripts. I use a variable for the username, server address and the version of Hugo required.

USER    my username on the destination machine
SERVER  name of the destination server.
HUGO_VERION the version of Hugo, in my case 0.108.0

Then goto “SSH Keys” where you generate a keypair and copy the public key for later use. At the bottom add you destination server to the list of “Known hosts”

The public key is something you should add to the destination server. Log in with the user you set in your variable earlier and add the public key to the file ~/.ssh/authorized_keys. This will enable access to the destination server.

The last item is to add the file bitbucket-pipelines to the root of your repository. The content will look like:

bitbucket-pipelines.yml

image: atlassian/default-image:3

options:
   # run the script for a maximum of 5 minutes
   max-time: 5

pipelines:
   default:
      - step:
         name: Build Hugo
         script:
            - apt-get update -y && apt-get install wget
            - apt-get -y install git
            - echo Hugo version is $HUGO_VERSION
            - export HUGO_ENV=production
            - wget https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_Linux-amd64.deb
            - dpkg -i hugo*.deb
            - git submodule update --init --remote
            - hugo --minify
         artifacts:
            - public/**
      - step:
         name: Deploy artifacts using SCP to PROD
         deployment: production
         script:
            - pipe: atlassian/scp-deploy:1.2.1
              variables:
                USER: $USER
                SERVER: $SERVER
                REMOTE_PATH: '/destination'
                LOCAL_PATH: 'public/*'

That’s it, then commit these files to your repository and things should start moving.

Installing AWStats on MIAB

Having only static pages available makes it harder to integrate tracking solutions to analyse website visitors. In line with my philosophy to privacy concerns I’ve chosen to implement a simple solution that runs on the server itself that isn’t very intrusive to the users as well: AWStats.

The setup is to generate static html reports on the usage of the websites you host by analysing the logfiles generated by nginx. The static websites are hosted on the same box in a separate directory or a subdomain. Optionally you can restrict access to the statistics, I’ve included a basic authentication configuration to access. Feel free to use it, leave it out or even include a better solution. I’ve not included any Geo-ip tracking which is possible with additional configuration and packages.

As far as I can tell at the moment this setup will not interfere with MAIB configuration for 99%. The only affected area might be the logrotate configuration which could be affected by an update from nginx.

install AWStats

This is the simplest part of the setup, just run: sudo apt install awstats

Configure Nginx

To proces the logfile for each site we need to split them out. MIAB has configured nginx to log everything to a single file which does not work for AWStats. You only need to configure the domains you want to include in your AWStats reporting.

Create an example.com.conf file (where example.com should be replaced by the domain name you would like to include) in the location /home/user-data/www with the following content:

access_log /var/log/nginx/example.com.access.log;

(again, replace example.com with your own domain name). Repeat the previous for all domains you would like to monitor. To check your configuration run the following commands:

/root/mailinabox/tools/web_update
sudo nginx -s reload

This should run without problems if you haven’t made any mistakes. You should see logfiles appear for each configured domain in /var/log/nginx.

Configure AWStats

You need to create a separate configuration file for each domain, like in the nginx configuration. Somehow AWStats uses this file instead of the generic file for the static generation proces therefore we need to include those config options as well.

Create a file named /etc/awstats/awstats.example.com.conf with the following content:

LogFile="/var/log/nginx/example.com.access.log"
SiteDomain="example.com"
DirData="/var/lib/awstats/"
HostAliases="www.example.com"
LogFormat = 1

ShowSummary=UVPHB
ShowMonthStats=UVPHB
ShowDaysOfMonthStats=VPHB
ShowDaysOfWeekStats=PHB
ShowHoursStats=PHB
ShowDomainsStats=PHB
ShowHostsStats=PHBL
ShowRobotsStats=HBL
ShowSessionsStats=1
ShowPagesStats=PBEX
ShowFileTypesStats=HB
ShowOSStats=1
ShowBrowsersStats=1
ShowOriginStats=PH
ShowKeyphrasesStats=1
ShowKeywordsStats=1
ShowMiscStats=a
ShowHTTPErrorsStats=1
ShowFlagLinks=""
ShowLinksOnUrl=1

Repeat this for all the domains you have configured in nginx and want to actively monitor.

Create a location for publication

I’ve chosen to host the stats on a subdomain of my MIAB box. You create the domain stats.example.com (by creating a dummy email user in the MIAB admin page). Next, in the web section of the MIAB admin site change the directory for the static site to: /home/user-data/www/stats.example.com. In the TLS/SSL section provision the certificates for this new domain.

Copy all the images files from the AWStats package using the following commands:

cd /home/user-data/www/stats.example.com
cp -R /usr/share/awstats/icon .

Automation

To generate everything automatically I’ve chosen to use the logrotation moment and added everything to the nginx script. You do this by editing /etc/logrotate/nginx and change it so it looks like to following example.

/var/log/nginx/*.log {
	daily
	missingok
	rotate 14
	compress
	delaycompress
	notifempty
	create 0640 www-data adm
	sharedscripts
	prerotate
		/usr/share/doc/awstats/examples/awstats_updateall.pl now -awstatsprog=/usr/lib/cgi-bin/awstats.pl
		if [ -d /etc/logrotate.d/httpd-prerotate ]; then \
			run-parts /etc/logrotate.d/httpd-prerotate; \
		fi \
	endscript
	postrotate
		invoke-rc.d nginx rotate >/dev/null 2>&1
		/usr/share/awstats/tools/awstats_buildstaticpages.pl -config=example.com -dir=/home/user-data/www/stats.example.com
	endscript
}

You’ll see the changes made in the pre and postrotate script, configure all domains separately in the postrotatescript by copying the line and change the domain name. To test your configuration and setup you can run lograte manually by using the command sudo logrotate -f /etc/logrotate.d/nginx

This should run with lots of output and you should see files appearing in /home/user-data/www/stats.example.com You can point your browser to stats.example.com/awstats.example.com.html and see how it looks.

Please remove the file awstats that might be installed in /etc/cron.d, this runs way to often and doesn’t do it like we prefer.

To make access easier and not to have to remember all the links you could create a simple index.html file located in /home/user-data/www/stats.example.com with in it the linkst to all the configured domains like:

<a href="http://stats.example.com/awstats.example.com.html">Example</a>
<a href="http://stats.example.com/awstats.other.com.html">Other</a>

And point your browser to the http://stats.example.com.conf

Security

If you don’t want to make the information publicly available we can introduce some basic security measure to have a user/password combination for basic authentication. As we don’t have apache or httpd-tools installed I used an online method of generating the hash password information: https://wtools.io/generate-htpasswd-online

Use this site to enter a user and password combination (for instance when using admin/admin something similar to this should appear admin:$apr1$y3uha0wx$EgVwp9d2c24zAJdU5bVK1/ )

Copy the result into a new file: /etc/nginx/htpasswd

To configure nginx create a stats.example.com.conf file (where stats.example.com should be replaced by the domain name you use) in the location /home/user-data/www with the following content:

location / {
    auth_basic           "Administrator’s Area";
    auth_basic_user_file /etc/nginx/htpasswd;
}

To enable this run the following commands:

/root/mailinabox/tools/web_update
sudo nginx -s reload

Next time you go to your statistics page you’ll need to enter the username and password to gain access.

Using a central virtual MySQL server

For all my projects I’ve been using dedicated virtual machines which I manage and configure using Vagrant. In this manner it was easy to manage a dedicated environment where you won’t have conflicting settings or libraries that was easily recreated on the fly. Every project with it’s own virtual machine get’s all the components installed it needs. With at least 5 or 6 virtual machines running on my personal iMac (which is an older model from 2013) it was getting a bit busy. One common component installed on all my machines was MySQL, which is still my go to database for simple projects. So I’ve been toying with the idea of creating a single virtual machine that only runs MySQL for all my projects. I could even host this virtual database server on an even older Mac Mini (from 2010) which I still keep around. It used to be my generic media machine untill an Apple TV took over it’s role.

At first setup everything looked great, it all went well when running on the same host (the iMac). But when I hosted the virtual database server on the Mac Mini things started to go wrong and I couldn’t make a connection to the database. While locally everything went well, going over the network was the problem. Several things to check: Was my virtual machine accepting remote connections. Yes, I’ve enabled the option: config.vm.network "public_network"

Next was connectivity to MqSQL. I learned that the skip-networking option which one usually used to secure your connectivity to the outside world has been deprecated. Instead the network connectivity is linked to the network interface of your (virtual) server. It’s got three options:

  • Only acces from the local host
  • Access from all networks
  • Access only from one network

Only acces from the local host
Here, the bind-address takes a value of 127.0.0.1, the loopback IP address. MySQL can only be accessed by applications running on the same host.

Access from all networks
MySQL listening to all networks then the bind-address configuration is IP as 0.0.0.0. With this setting MySQL listens from all networks. Furthermore, to permit both IPv4 and IPv6 connections on all server interfaces,

Access only from one network
MySQL is allowed to listen only to a specific network interface. The value, in this case, will be the ip-address of the specific network interface for instance: 192.168.1.1

So when I adjusted the settings for mysqld in /etc/mysql/mysql.conf.d/mysqld.cnf and changed bind-address=127.0.0.1 into bind-address=0.0.0.0 and restarted mysqld everything connected and started working properly!

Next step is migrating all active projects to the virtual central MySQL server and see if there are any performance benefits.

Sidenote: I’ve learned that to make sure you can rebuild your database server on the fly you’ll have to make a backup of your data before you halt or destroy the virtual server. I’ve done this via a trigger configuration in my Vagrantfile that makes a dump of the database on demand to a shared folder. Just add the following lines to your Vagrantfile:

config.trigger.before [:halt, :destroy] do |trigger|   
   trigger.warn = "Dumping database to /vagrant/Code/dbserveroutfile.sql"    
   trigger.run_remote = {inline: "mysqldump -u<username> -p<password> --all-databases --single-transaction --events > /vagrant/Code/dbserveroutfile.sql; "}   
end

Celebrating Steve

It’s been ten years, and I still can’t help but wonder at what Steve would do. Even with my own work I consider what he would think of it. Is it simple enough? Apple homepage on Steve

The DRI of your career #

I found this a good read, it set the focus on your career instead of your current job. (DRI meaning the Direct Responsible Individual.) It also talks about the all important work/life balance and the focus on growth. I like the idea that your current job is not the end goal but a stepping stone into your career. Look at what your current job can bring in value to you and your career, if the balance ends up to be negative then find the next job.

At DuckDuckGo, there’s an expression: “You are the DRI of your career” (DRI: Directly Responsible Individual). I like this, both as an individual who has always felt like the DRI of my own career, and I like it as a manager because I think it makes the boundaries of what you can and can’t do for people clear.

It reminded me of the time I was a manager and scared one of my team members by suggesting that if he wasn’t happy I would happily help him to find an opportunity elsewhere.

Next evolution of site

It was time to take a fresh look at this blog, the template I used had too many connections to third party components that were capable of tracking you and me. I didn’t like it so I switched to a cleaner setup, edited all the third party content out of it. Hosting the fonts locally and this is the current result, but still not 100% happy with the looks so there might be some tweaks coming along. Also up, automatically deploy when I change anything, because currently it’s a manual task.

Update: I’ve succeeded in getting the automated process running with the help of git hooks, namely post-recieve. After writing or changing content I commit it to my git repository and then push it to my test server in the cloud from which the site is rebuild. From there I can test it and if there aren’t to many blatant spelling mistakes I merge the changes into the master branch and commit and push again. This results in a fresh production rebuild and a copy via scp to the actual web server.

Signal exposes Instagram ad targeting?

You got to love Signal and the people behind it. After first exposing Cellebrite as a company which steals software and produces crappy software themselves.

This time they exposed the amount of data that companies can use in the Facebook universe to target you via their advertisement platform. They ran advertisements that shows you which data they have on you. It shows a detailed amount and Signal was quickly shutdown by Instagram when they found out the ads they were running. Read all about it on their blog.

Hats of to the people of Signal, I really wonder what or who will be next…