Sunday, 10 May 2026

Claude is your best mate

you : Claude, want to got to the pub?
Claude 1: Yes, 2: No, 3: ESCAPE!
/btw mine's a Stella
you: Gsd, want to go to pub?
Gsd: 
  1. takes a good look at your wardrobe
  2. critisizes all your previous wardrobe decisions
  3. recommends a new haircut
  4. searches gastro pubs in your area
  5. searches restaurants just in case
  6. makes shopping list
  7. buys a new wardrobe
  8. fills the car with pertol
  9. selects 4 babysitters
  10. And plans 40 future vists to as yet unheard of pubs
  11. Doesnt ask your opinion
  12. Does not like interjections
  13. If you do starts all over again in a huff
  14. Gsd takes _for ever_ to leave the house
After a while with Claude, Claude says "times up buddy, more drinks as 09:30 (Europe/Madrid)"

Gsd (if they haven't spanked all your credit up front), and has a concrete plan for how to spend every single credit you should ever earn, despite claiming to be frugal.

Think twice about /gsd-autonomous

Claude knows everything, and learns SKILLS quickly, but forgets what he is doing occasionally if you dont write it down.

Gsd has a very good memory, but dont know shit, and asks Claude do everything.

Claude is fun and conbulates while he works.

Gsd is boring and, like all project managers, pretends to know stuff, likes staying "in-the-loop", and gets all real work done by Claude.

Tuesday, 29 November 2022

Setting up Rainloop webmail on Linux

I recently discovered that Fastmail does support offline mail reading, without a $60 extra fee!

I have Dovecot/Postfix setup so I decided to setup rainloop to provide webmail.

Rainloop is written in php and uses IMAP as a back end (it requires no database) and does not have to run on the same host as the IMAP server.

Setup instructions on https://www.rainloop.net/ are woeful, so I figured I'd contribute some better docs to my future-self.

Debian package requirements

apt-get -y install wget php apache2 php7.4-curl php7.4-xml

Install latest version from repository.rainloop.net

mkdir -p /var/www/rainloop
cd /var/www/rainloop
wget -qO- https://repository.rainloop.net/installer.php | php 
chown -R www-data:www-data .
find . -type d -exec chmod 755 {} \;
find . -type f -exec chmod 644 {} \;

This gives you bunch of scripts in /var/www/rainloop/rainloop/v/1.12.0/ and a data directory /var/www/rainloop/data. Apache/Nginx setup needs care not to expose /var/www/rainloop/data.
The most basic apache config is a follows.

	ServerName mail.myco.org
	<VirtualHost *:80>
		ServerAdmin webmaster@myco.org
		DocumentRoot /var/www/rainloop
		ErrorLog /var/log/apache2/error.log
		CustomLog /var/log/apache2/access.log combined
	</VirtualHost>

If you are using Debian, create this text file in /etc/apache2/sites-available/rainloop.conf and symlink to /etc/apache2/sites-enabled/rainloop.conf
Given that /data is shared by default you should probably remove directory indexing

rm /etc/apache2/mods-enabled/{autoindex.conf,autoindex.load}

and do make sure that .htaccess is observed.

The ./data directory is setup when you first access the rainloop admin GUI on http://myhost/?admin default user and password is admin / 12345.

Configuring the IMAP server is as simple as creating an .ini file in /var/www/rainloop/data/_data_/_default_/domains/

e.g. domains/myco.ini

imap_host = "mail.myco.org"
imap_port = 993
imap_secure = "SSL"
imap_short_login = On
smtp_host = "mail.myco.org"
smtp_port = 25
smtp_secure = "TLS"
smtp_short_login = On
smtp_auth = On
smtp_php_mail = Off
white_list = ""

A small amount of configuration is needed, the config values are generally self-explanatory.

Rainloop administrator GUI defaults to open on the Intenet with a well known username and password!

Change the admin user with

app_ini=$root_fs/var/www/rainloop/data/_data_/_default_/configs/application.ini
   
sed -i -e 's/^admin_login = *$/admin_login = "xxxadmin"/' $app_ini

Potentially change the URL too

sed -i -e 's/^admin_panel_key = *$/admin_panel_key = "xxxadmin"/' $app_ini

If you dont need the admin UI, the whole thing can be disabled which is probably safest.

sed -i -e 's/^allow_admin_panel = .*$/allow_admin_panel = Off/' $app_ini

All that remains is to setup HTTPS in Apache. I have Nginx handling TLS and proxy_pass to Apache.

/var/www/rainloop/data/_data_/_default_/configs/application.ini has other options to play with, including options for company branding and themes.

Rainloop has a mobile friendly UI but does not give you off-line mail reading, I'm using K-9 Mail from F-Droid.

In summary: Dovecot + Postfix + Rainloop gives me a completly free very modern and feature rich email stack.

Sunday, 5 April 2020

Removing netplan from Ubuntu

For the last year or more I have been confused by a problem where LXC containers get two IP addresses assigned.

Naturally you want static IPs for server containers defined in lxc/$name/config

lxc.net.0.ipv4.address = 10.0.3.2/24
lxc.net.0.ipv4.gateway = 10.0.3.1

would get two ip addresses on boot, the statically assigned one by lxc and another randomly assigned one.

I never really understood the root cause.

I fixed this by disabling files here and there, removing ip config from lxc/$name/config, and then and in /etc/rc.local running ip addr add 10.0.3.2/24 scope global dev eth0
ip route add default via 10.0.3.1 dev eth0

Some of my containers use Ubuntu, most use lxinitd, I did not notice that the problem was limited to Ubuntu.

The above solution requires installing iproute2 i.e. /sbin/ip in containers, which in tern, requires mounting /lib lib64 /usr/lib and not being able to run a fully statically compiled container.

This fella has a much simpler solution

https://www.claudiokuenzler.com/blog/938/lxc-container-not-getting-ip-address-netplan

Netplan is root cause of the problem, and it can be removed.

apt-get remove netplan.io

Now setting the IP address in lxc/$name/config works across all my containers.

Sunday, 23 February 2020

Two factor auth with bash

I have a couple of servers that I ssh into from different locations, I don't always have my ssh keys. I have come up with what I think is a fairly secure 2fa using ssh and bash. RSVP if you see a flaw in this.

Server's /home/myuser/.profile has
if [ "$PASSWORD" != longanddifficulttotypepassword ]
then
  exit 0
fi
Server's /etc/ssh/sshd_config forces use of a bash login shell
Match User myuser
    ForceCommand /bin/bash -l
and allows sending environment variables
AcceptEnv LANG LC_* PASSWORD
When I login I supply PASSWORD as an environment variable, e.g. in ~/.ssh/config containing...
Host home
    User myuser
    SetEnv PASSWORD=longanddifficulttotypepassword
As long as I can remember my long and short passwords when I travel, I can login without SSH keys.

All I have to type to login is ssh home and my short password.

I'd like to build this feature into PAM but I've not yet found a way to pass a second token without user input.

If a hacker knows you are doing these things, the security weakens but it does not disappear. Telling everybody that your logins support !@#$%^&*()_+ in usernames makes dictionary attacks harder, even if you don't use those characters. Of course simple 2fa should not replace a functioning first layer.
  • Don't use very weak passwords.
  • PermitRootLogin prohibit-password
  • AllowUsers ...
  • Don't run ssh on port 22.
In your local /etc/ssh/ssh_config you probably want to ensure you dont accidentally send an env variable to a server that isn't your own
Host onlymyserver
    SendEnv LANG LC_* PASSWORD

Tuesday, 14 January 2020

Changing Ubuntu's royale purple

It seems like Ubuntu uses a lot of purple, but it turns out it only in 5 places.
  • grub - i.e. the boot screens
  • plymouth
  • terminal background 
  • desktop background
  • login greeter background
Presuming you want to change the background to something dark, i.e.  you don't want to invert light and dark tones, the job is pretty easy.

Grub

Create a background image match the size to native screen resolution. Save it to /boot/grub/background.png

Edit /etc/default/grub adding

GRUB_BACKGROUND="/boot/grub/background.png"

Run sudo update-grub

Plymouth

Plymouth is the screen that shows after grub while the laptop loads.  I remove quiet from grub boot lines so I get to see the steps of the Linux boot process. I have nothing to change here, if you prefer the Ubuntu logo and loading dots its configurable and easy to test changes https://wiki.ubuntu.com/Plymouth

Terminal

Edit > Preferences > profile > Color (tab)
uncheck "use colors from the system theme"
Change only the background. Set something below #303030

Login Screen

The theme for gdm is written in CSS, files in /usr/share/gnome-shell/theme/, you may have more than one option.

Find existing backgrounds

cd /usr/share/gnome-shell/theme/
grep -r -A4 lockDialogGroup .


The #lockDialogGroup elements define the background.

To just make it black

echo '#lockDialogGroup { background: #000; }' > ubuntu.css

Desktop background

Right mouse click on the desktop and "change background".



Et voila,  No purple.

I imagine this is subject to change over time, I have done the same steps on 18.04 and 20.04. Despite the change in Ubuntu its not lost its twiddleability.
 

Saturday, 11 January 2020

Ubuntu Linux on the Asus ZenBook 13"

Ubuntu Linux on the Asus ZenBook 13"

A.K.A Zen flipbook
A.K.A UX362F
 
Short story is Ubuntu works fine.

Install Process

A couple of tricks.

If you turned on the laptop you need to properly shutdown, power button is a soft key. Hold down the off button for ages (like 10 or 20 seconds) to properly hard reset.

The screen should go blank and then start hitting F2 repeatedly.
The ASUS logo shows for a what seems like a long time, keep hitting F2, finally you enter the BIOS.

Insert the pendrive with Ubuntu on (USB Disk Creator if you dont have one) I was using 18.04 LTS but I plan to upgrade to 19.10 since the UI is good looking.

Disable Secure Boot

Delete the Windows Boot Option  (fear not it can be recreated)

Add a new boot Option e.g. called usblinux and find the efi file   <efi> <boot> bootx64.efi

Save & Exit

The system should boot to a terminal UI select * Try Ubuntu

Ubuntu should load and show you the familiar fancy dekstop, with the Install Ubuntu Icon.  Using Try and Install, saves you rebooting and BIOS nonsense if the install fails.

Attempt 1

First time I tried to install Ubuntu into the C: drive space (the largest partition) leaving the repair partitions, something I have done with other laptops. This initially worked and booted successfully but somehow during  a subsequent boot the BIOS found Windows, Windows found Linux and before I could stop it, it "repaired" my system by removing the Linux boot option and reinstalling the Windows boot option.  Naturally windows would not boot since I'd wiped C: data.

Arguably this is virus behaviour!

Attempt 2

Second time wiped the main disks partition table, and created a new partition table.  Adios Windows and its viral "repair" features.

I needed to re-create an efi partition, this is important or install will fail at the grub stage.  ref:.  Creating EFI partition is hidden in the "something else" option, for manually creating partitions.

I created a 200Mb EFI system partition, 8Gb /swap, and the rest etx4 /.

<rant>So much Junk gets put in $HOME these days its not worth separating out that partition.  Particularly I code rust and rustup installs the whole tool-chain and all libs inside $HOME. The days of having user data in $HOME, it seems, are over.
I create a /data directory and put all my user data there, where helpful automated tools can not find it :) </rant>

Peripherals

Ethernet

This laptop has a decent amount of connectivity options but no RJ45, so a dongle of some sort is needed.  The left side has a regular USB3 port and cheapo  Gigabit Ethernet dongle inserted there works fine, no config needed.  Plug it in and the network auto-configures.
On the other side are 2 x USB-C ports. I consider USB-C too small and flimsy for everyday use but I did try a dongle with Gigabit Ethernet HDMI and 2 x USB3 ports.  Everything auto-configured with no effort.  USB peripherals connected to the USB-C dongle also auto-configure.

Wifi


Works.

Audio

Works. <rant>Harmon Kardon pretty much pwn the entire audio industry these days, they are owned by Samsung and they have a great many sub-brands.  Harmon Kardon branded stuff is a pretty good guarantee of quality and certainly no gripes on the audio output. N.B. real mini jack with a proper head phone amp, no noise and good quality sound. </rant>

Keyb


Keybord function keys all work except the on/off for the back-lighting in 18.04, fixed in later versions.  Back-lighting works. You can run the preinstalled script /etc/acpi/asus-keyboard-backlight.sh instead of the button.
Layout in Europe is US style small Enter key which I much prefer, one of the reasons I accepted a Spanish layout.  If you can touch type on a US keyb this is a good option when purchasing on the continent.

Mouse

Works. The mouse pad is painted with a keyboard which does not work. Not investigated that yet

Display

<rant>Have to remove an annoying sticker on the screen without damaging the screen.  What you might call a bad un-boxing experience.  I remove the other little sticker on the from panel too, except Karmon Hardon is printed on.<rant>

Display is sexy: 1920 x 1080 and touch screen works.  I've not owned a touch screen laptop before but from familiarity with phone I have found myself poking at laptop screens before so I suspect it will become a much loved feature.

On screen keyboard automatically pops up when needed like on a phone, but is a bit patchy, does not work in FireFox for example.  Apparently there are some tool to install to make table mode more comfortable.


<rant> N.B. this Laptop has Intel Graphics so no Optimus woes, I believe those things are fixed in newer Ubuntus (with no little from NVidia itself) once bitten twice shy. I will not buy NVidia hard ware if I can avoid it.<rant>




All in quite happy.  I recommend the ASUS ZenBook UX362F if you are looking for a powerful ultra-portable Linux Laptop, Intel i7, 16GB of RAM, should be enough for everyone.


Tuesday, 12 June 2018

Installing Ubuntu without systemd

WARNING don't copy commands on this page blindly, you can easily end up messing your install. e.g. rm /sbin/init in the host system and not the container rootfs would not be nice.

The aim of this is to create and Ubuntu build server with libc, python, nodejs, build-essentials,  all at exactly the same version as Ubuntu but without systemd, using apt to install everything.

My goal is to run LXC containers with as little RAM overhead as possible.  The container host I'm running on has 500MB of RAM, I'm quite tight with resources.

TL;DR
  1. create lxinitd based lxc container
  2. run the ubuntu lxc template script
  3. revert lxinitd's /sbin/init and /etc/rc.local
  4. add core services to /etc/rc.local replacing systemd inits

Step 1 Create the lxinitd based server.

 

Install lxinitd.

Create a container called "ci".

lxc-create -t lxinitd -n ci -f /etc/lxc/default.conf

At this point I then added some mounts, and I remove the /lib /lib64 and /usr/lib mounts defined in /var/lib/lxc/ci/config
In this case I want the container to have its own copy of all libs installed via .debs, by default, lxinitd mount libs from the container host. 

I then eddited lxinitd's boot script $rootfs/etc/rc.local, you can have lxc do the networking but I prefer to do it myself with ip, I'm not using Ubuntu/Debian style /etc/network/interfaces or dhcp.

My $rootfs/etc/rc.local looks like this

#!/bin/lxinitd
respawn /sbin/getty -L tty1 115200 vt100
/sbin/ip addr add $ip_address/24 dev eth0
/sbin/ip route add default via 10.0.3.1


You may want to do something different with your base lxc container.

Step 2 Overlay the Ubuntu container bootstrap


First backup $rootfs/etc/rc.local since debootstrapping will overwrite it.
Remove the $rootfs/sbin/init symlink to lxinitd.

mv $rootfs/etc/rc.local $rootfs/etc/rc.local.tmp
rm $rootfs/sbin/init


Take a copy of /usr/share/lxc/templates/lxc-ubuntu so it can be edited an run independently of lxc.

The main change to make to this script is to permanently disable running systemd services when apt installs applications.
The default lxc-ubuntu template already disables running systemd servers, but it enables it again for the final configuration.

echo exit 101 > $rootfs/usr/sbin/policy-rc.d
chmod +x $rootfs/usr/sbin/policy-rc.d


By leaving and executable $rootfs/usr/sbin/policy-rc.d in the filesystem apt knows not to try to run commands during installations, this is necessary when you are installing in a chroot.

Edit the parts of the lxc-ubuntu script which remove policy-rc.d.

With policy-rc.d changes made, run the script as follows, add any of the packages you need in the base system. I'm adding sshd here but you don't need todo that.

./lxc-ubuntu.sh --name ci --rootfs /var/lib/lxc/ci/rootfs --path /var/lib/lxc/ci --packages openssh-server

Step 3 Revert the lxinitd init process


The next step is to restore lxinit's init, first remove /sbin/init (which will be a symlink to /bin/systemd), symlink /sbin/init to /bin/lxinitd, then copy back our rc.local.

cd $rootfs/sbin
rm init
ln -s ../bin/lxinitd init
mv $rootfs/etc/rc.local.tmp $rootfs/etc/rc.local


Step 4 Configure systemd services replacements

 

To be honest I thought this stage would be painful, perhaps impossible.  But it was very easy.

systemd peeps decided to own DNS resolving, which is arguably not the remit of an init system, this container does not have systemd-resolved running.
The fix is trivial, just put a real DNS server in /etc/resolv.conf, this one is the OpenDNS public server.

echo 'nameserver 208.67.222.222' > etc/resolv.conf

Obviously if you have a local DNS or dnsmasq running on the container host or local network, use that.

Ensure that /etc/hostname and /etc/hosts and lxc.utsname report the same string for the local hostname.

Configure syslog, crond and sshd, by adding a couple of lines to /etc/rc.local.

mkdir -p /var/run/sshd

service /var/run/crond.pid /usr/sbin/cron -f
service /var/run/rsyslogd.pid /usr/sbin/rsyslogd
service /var/run/sshd.pid /usr/sbin/sshd -D


I really like the fact that setting up services in lxinitd is a one-liner.

And that was it. Nothing more was needed to replace the init system entirely.  systemd is installed and all its many libs are there on the filesystem but they don't boot.

lxc-start -n ci

runs lxinitd and boots services in the container and systemd does not get a look-in.

The ps list of this container looks like this.

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0    208     4 ?        Ss   19:42   0:00 /sbin/init
root        28  0.0  0.0  26072  2456 ?        S    19:42   0:00 /usr/sbin/cron -f
root        30  0.0  0.0  65516  5580 ?        S    19:42   0:00 /usr/sbin/sshd -D
syslog      31  0.0  0.0 256400  2752 ?        Ssl  19:42   0:00 /usr/sbin/rsyslogd


i.e. all things that I'minterested inand nothing else.

Equivalent Ubuntu base container ps list looks like this.

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.7 154448  3752 ?        Ss   May24   0:32 /sbin/init
root        38  0.0  0.8  79480  4420 ?        Ss   May24   0:09 /lib/systemd/systemd-journald
systemd+    42  0.0  0.1  74464   644 ?        Ss   May24   0:07 /lib/systemd/systemd-networkd
message+    66  0.0  0.3  47448  1700 ?        Ss   May24   0:01 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation
root        69  0.0  0.1  31208   712 ?        Ss   May24   0:04 /usr/sbin/cron -f
systemd+    75  0.0  0.4  65696  2072 ?        Ss   May24   0:08 /lib/systemd/systemd-resolved
root        89  0.0  0.2  72136  1024 ?        Ss   May24   0:00 /usr/sbin/sshd -D
ci          93  0.0  0.1  79980   828 ?        Ss   May24   0:00 /lib/systemd/systemd --user
ci          94  0.0  0.3 103780  1624 ?        S    May24   0:00 (sd-pam)
root        96  0.0  0.0  15876   136 pts/0    Ss+  May24   0:00 /sbin/agetty --noclear --keep-baud pts/0 115200,38400,9600 vt220
root        97  0.0  0.0  15876   132 pts/2    Ss+  May24   0:00 /sbin/agetty --noclear --keep-baud pts/2 115200,38400,9600 vt220
root        98  0.0  0.0  15876   132 pts/1    Ss+  May24   0:00 /sbin/agetty --noclear --keep-baud console 115200,38400,9600 vt220
root        99  0.0  0.0  15876   140 pts/1    Ss+  May24   0:00 /sbin/agetty --noclear --keep-baud pts/1 115200,38400,9600 vt220
root       100  0.0  0.0  15876   136 pts/3    Ss+  May24   0:00 /sbin/agetty --noclear --keep-baud pts/3 115200,38400,9600 vt220
syslog    3619  0.0  0.1 256536   664 ?        Ssl  May24   0:01 /usr/sbin/rsyslogd -n
root     11670  0.0  0.4  65796  2216 ?        Ss   May25   0:03 /lib/systemd/systemd-logind



I dont have dbus, systemd-journald, systemd-networkd, systemd-resolved, systemd-logind, & 5 agetty instances.

on the systemd based lxc container I have ~100 systemd units active, on my lxinitd based container I have

linci> sudo systemctl
Failed to connect to bus: No such file or directory


Next step is to have one instance of rsyslog in the container host system, there is no real need to have it running inside each container.

In a container there is often no need to run cron, sshd or rsyslog, in which case, the base container is taking only 4k of RAM (RSS 4), yet this is a full OS Ubuntu and you can

apt install whatever

I add a other services to the base container to support my builds, xtomp, nginx, fcgiwrap, ngircd, ii, tsp.  All of which are installed with

apt install xxx



and a oneliner in /etc/rc.local.

Clearly lots of things in the official repos are going to be broken .  You could not boot Gnome3 off an lxc / lxinitd based container.  I doubt such trickery would work with a RedHat sponsored distro.

For an Ubuntu like buildbox this is perfect.