PiKVM is a specialized RaspberryPi 4 appliance for remote controlling one or more computers over the internet.
It makes sense to leave a RaspberryPi 4 running 24×7 but shutdown a much more power hungry computer for example a TrueNAS.
It is possible to extend the PiKVM main menu with more services. It is also not very hard to add PHP to the Arch Linux ARM that powers PiKVM.
PiKVM uses nginx as the web server that acts as a switch in front of the different services that make up PiKVMs remote control capability.
Usually the root filesystem and with that the /etc folder is read only. The way DokuWiki is installed by defualt on Arch Linux this means that the configuration settings including the users for the wiki are can not be changed without executing some additional commands:
rw # This alone is not enough, the php interpreter still thinks the conf directory is read only systemctl restart php-legacy-fpm kvmd-nginx # Change settings or add user ro
dokuwiki uses php, not the very latest version, together with nginx this is php-legacy-fpm.
rw pacman -S php-legacy-fpm dokuwiki systemctl enable php-legacy-fpm # Created symlink /etc/systemd/system/multi-user.target.wants/php-fpm-legacy.service -> /usr/lib/systemd/system/php-fpm-legacy.service. systemctl start php-legacy-fpm
cd /etc/php-legacy/
total 88 drwxr-xr-x 2 root root 4096 Jan 16 22:58 conf.d drwxr-xr-x 2 root root 4096 Apr 11 15:38 php-fpm.d -rw-r--r-- 1 root root 5331 Apr 11 16:09 php-fpm.conf -rw-r--r-- 1 root root 72933 Apr 3 06:02 php.ini
We want to prepare php-fpm for larger file uploads than configured by default: nano /etc/php-legacy/php.ini
[...] ;;;;;;;;;;;;;;;; ; File Uploads ; ;;;;;;;;;;;;;;;; [...] ; Maximum allowed size for uploaded files. ; https://php.net/upload-max-filesize upload_max_filesize = 50M [...] ;;;;;;;;;;;;;;;;; ; Data Handling ; ;;;;;;;;;;;;;;;;; [...] ; Maximum size of POST data that PHP will accept. ; Its value may be 0 to disable the limit. It is ignored if POST data reading ; is disabled through enable_post_data_reading. ; https://php.net/post-max-size post_max_size = 50M
nano /etc/php-legacy/php-fpm.d/www.conf
Check the users at the top of the file: The user for every file php has to work with is http, the user for the socket is different: kvmd-nginx You need to change
listen.owner = kvmd-nginx listen.group = kvmd-nginx
; Start a new pool named 'www'. ; the variable $pool can be used in any directive and will be replaced by the ; pool name ('www' here) [www] ; Per pool prefix ; It only applies on the following directives: ; - 'access.log' ; - 'slowlog' ; - 'listen' (unixsocket) ; - 'chroot' ; - 'chdir' ; - 'php_values' ; - 'php_admin_values' ; When not set, the global prefix (or /usr) applies instead. ; Note: This directive can also be relative to the global prefix. ; Default Value: none ;prefix = /path/to/pools/$pool ; Unix user/group of the child processes. This can be used only if the master ; process running user is root. It is set after the child process is created. ; The user and group can be specified either by their name or by their numeric ; IDs. ; Note: If the user is root, the executable needs to be started with ; --allow-to-run-as-root option to work. ; Default Values: The user is set to master process running user by default. ; If the group is not set, the user's group is used. user = http group = http ; The address on which to accept FastCGI requests. ; Valid syntaxes are: ; 'ip.add.re.ss:port' - to listen on a TCP socket to a specific IPv4 address on ; a specific port; ; '[ip:6:addr:ess]:port' - to listen on a TCP socket to a specific IPv6 address on ; a specific port; ; 'port' - to listen on a TCP socket to all addresses ; (IPv6 and IPv4-mapped) on a specific port; ; '/path/to/unix/socket' - to listen on a unix socket. ; Note: This value is mandatory. listen = /run/php-fpm-legacy/php-fpm.sock ; Set listen(2) backlog. ; Default Value: 511 (-1 on FreeBSD and OpenBSD) ;listen.backlog = 511 ; Set permissions for unix socket, if one is used. In Linux, read/write ; permissions must be set in order to allow connections from a web server. Many ; BSD-derived systems allow connections regardless of permissions. The owner ; and group can be specified either by name or by their numeric IDs. ; Default Values: Owner is set to the master process running user. If the group ; is not set, the owner's group is used. Mode is set to 0660. listen.owner = kvmd-nginx listen.group = kvmd-nginx ;listen.mode = 0660
Also we need to relax a security mechanism in sysetmd that php-legacy-fpm uses:
export EDITOR=/usr/bin/nano # else the editor will be vim. Use i to enter insert mode, make the changes, ESC, :x systemctl edit php-legacy-fpm.service
### Editing /etc/systemd/system/php-fpm-legacy.service.d/override.conf ### Anything between here and the comment below will become the contents of the drop-in file [Service] ProtectSystem=true ### Edits below this comment will be discarded ### /usr/lib/systemd/system/php-fpm-legacy.service # # It's not recommended to modify this file in-place, because it # # will be overwritten during upgrades. If you want to customize, # # the best way is to use the "systemctl edit" command. # # [Unit] # Description=The PHP FastCGI Process Manager [...] # # Mounts the /usr, /boot, and /etc directories read-only for processes invoked by this unit. # ProtectSystem=full
Successfully installed edited file '/etc/systemd/system/php-fpm-legacy.service.d/override.conf'.
You can format and mount any device Linux and the Raspberry Pi can talk to (USB keys, external USB drives, network filesystems). DokuWiki is set up on ArchLinux to use /var/lib/dokuwiki to store any data that is not part of its core code like data and plugins for add ons and tpl for different looks.
So for example we can attach an USB key and format it using ext4. Then we mount it at a temporary location and move the contents of /var/lib/dokuwiki there. When we have moved everything we then can mount the USB key to /var/lib/dokuwiki and making this permanent in /etc/fstab
fdisk /dev/sda
Welcome to fdisk (util-linux 2.38.1). Changes will remain in memory only, until you decide to write them. Be careful before using the write command. This disk is currently in use - repartitioning is probably a bad idea. It's recommended to umount all file systems, and swapoff all swap partitions on this disk. Command (m for help): p Disk /dev/sda: 7.5 GiB, 8053063680 bytes, 15728640 sectors Disk model: USB DISK Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: gpt Disk identifier: AAE09444-894D-4F1F-AD63-B413B8D6B5F2 Device Start End Sectors Size Type /dev/sda1 2048 15728606 15726559 7.5G Microsoft basic data Command (m for help): q
mkfs.ext4 /dev/sda1 # in the next steps replace a5c127c4-439a-4ab4-97c2-27c4910036c5 with the UUID value of the output of mkfs.ext4 lsblk -o NAME,SIZE,RO,TYPE,LABEL,UUID,MOUNTPOINTS
NAME SIZE RO TYPE LABEL UUID MOUNTPOINTS sda 7.5G 0 disk `-sda1 7.5G 0 part a5c127c4-439a-4ab4-97c2-27c4910036c5 mmcblk0 14.8G 0 disk |-mmcblk0p1 256M 0 part PIBOOT BE9C-7C3A /boot |-mmcblk0p2 256M 0 part PIPST 8ac2bdd9-4be5-4ed2-a352-9d6a6458248d /var/lib/kvmd/pst |-mmcblk0p3 6G 0 part PIROOT e9d84664-4af4-49e2-b4eb-926a6679afcf / `-mmcblk0p4 8.3G 0 part PIMSD 0edfeabf-57a0-4f74-9160-bdc4234a4246 /var/lib/kvmd/msd
mount UUID=a5c127c4-439a-4ab4-97c2-27c4910036c5 /mnt mv /var/lib/dokuwiki/* /mnt umount /mnt nano /etc/fstab
[...] LABEL=PIPST /var/lib/kvmd/pst ext4 nodev,nosuid,noexec,ro,errors=remount-ro,data=journal,X-kvmd.pst-user=kvmd-pst 0 0 LABEL=PIMSD /var/lib/kvmd/msd ext4 nodev,nosuid,noexec,ro,errors=remount-ro,data=journal,X-kvmd.otgmsd-user=kvmd 0 0 # add the following line here UUID=a5c127c4-439a-4ab4-97c2-27c4910036c5 /var/lib/dokuwiki ext4 nodev,nosuid,noexec,rw,errors=remount-ro,data=journal 0 0
systemctl daemon-reload mount /var/lib/dokuwiki
mkdir -p /usr/share/kvmd/extras/dokuwiki (or cd)
Two files: nano /usr/share/kvmd/extras/dokuwiki/manifest.yaml
name: DokuWiki description: A DokuWiki instance icon: dokuwiki/lib/tpl/dokuwiki/images/logo.png path: dokuwiki daemon: kvmd-webterm place: 10
nano /usr/share/kvmd/extras/dokuwiki/nginx.ctx-server.conf
#Remember to comment the below out when you are installing DokuWiki, and uncomment it when you are done. location ~ (data/|conf/|bin/|inc/|install.php) { deny all; } # secure Dokuwiki # location ~ \.ht { deny all; } # also secure the Apache .htaccess files # location @dokuwiki { # root /usr/share/webapps; # #rewrites "doku.php/" out of the URLs if you set the userewrite setting to .htaccess in dokuwiki config page # rewrite ^/dokuwiki/_media/(.*) /dokuwiki/lib/exe/fetch.php?media=$1 last; # rewrite ^/dokuwiki/_detail/(.*) /dokuwiki/lib/exe/detail.php?media=$1 last; # rewrite ^/dokuwiki/_export/([^/]+)/(.*) /dokuwiki/doku.php?do=export_$1&id=$2 last; # rewrite ^/dokuwiki/(.*) /dokuwiki/doku.php?id=$1&$args last; # } location = /dokuwiki { return 301 /dokuwiki/; } location /dokuwiki/ { root /usr/share/webapps; index doku.php; # try_files $uri $uri/ @dokuwiki; } # Allow larger uploads (e.g. 50 MB) client_max_body_size 50m; location ~ \.php$ { root /usr/share/webapps; try_files $uri =404; # default fastcgi_params include /etc/nginx/fastcgi_params; # fastcgi settings fastcgi_pass unix:/run/php-fpm-legacy/php-fpm.sock; fastcgi_index index.php; fastcgi_buffers 8 16k; fastcgi_buffer_size 32k; # fastcgi params fastcgi_param DOCUMENT_ROOT $realpath_root; fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; include /etc/nginx/fastcgi.conf; }
For using install.php to setup dokuwiki change the deny all location ~ to
#Remember to comment the below out when you are installing DokuWiki, and uncomment it when you are done. location ~ (data/|conf/|bin/|inc/) { #|install.php) { deny all; } # secure Dokuwiki
systemctl restart php-legacy-fpm kvmd-nginx
Now you can open https://pikvm/dokuwiki/install.php