PantherX OS Server on Hetzner Cloud

These two scripts make it easy to install PantherX OS Server on a Hetzner Cloud Server. Depending on what you want to achieve, you may only need to run the first script:

  1. Install from binary: This is enough if you want to deploy to the server
  2. Reconfigure to include PantherX repositories

1. Install from binary

#!/bin/bash

# PantherX on Hetzner

# Test on:
# - Ubuntu 21.04
# - Debian 11
#
# 1. Create a new CCX11 with Debian 11
# 2. Login with SSH
# 3. Paste this script into a setup.sh and run it
# 4. Wait ~10 minutes on a 25 Euro Cloud Server
#
# If you just want to deploy to the target machine, from your PantherX installation, this is all you need to do.
# If you want to operate on the target machine directly, you need to run the 2nd script pantherx-on-hetzner-cloud_second.sh
#
# Modify below values to suit your needs. Change the password!

###### MODIFY

TIMEZONE="Europe/Berlin"
LOCALE="en_US.utf8"
USERNAME="panther"
USER_COMMENT="panther's account"
USER_PASSWORD="6a4NQqrp84Y7mj56"

HOSTNAME='pantherx'

###### MODIFY END

if [ "$USER_PASSWORD" == "6a4NQqrp84Y7mj56" ]; then
	echo "######### IMPORTANT #########"
	echo "You did not modify the default user password. Overwriting ..."
	USER_PASSWORD=$(openssl rand -base64 24)
	echo
	echo "#########"
	echo $USER_PASSWORD
	echo "#########"
	echo
fi

CONFIG=/etc/bootstrap-config.scm
CHANNELS=/etc/channels.scm
CRYPT='$6$abc'

apt-get update -y
apt-get install curl xz-utils -y
# Uncomment this for Debian 9
# sed -i '/^mozilla\/DST_Root_CA_X3/s/^/!/' /etc/ca-certificates.conf && update-ca-certificates -f
wget https://ftp.gnu.org/gnu/guix/guix-binary-1.3.0.x86_64-linux.tar.xz
cd /tmp
tar --warning=no-timestamp -xf ~/guix-binary-1.3.0.x86_64-linux.tar.xz
mv var/guix /var/ && mv gnu /
mkdir -p ~root/.config/guix
ln -sf /var/guix/profiles/per-user/root/current-guix ~root/.config/guix/current
export GUIX_PROFILE="`echo ~root`/.config/guix/current" ;
source $GUIX_PROFILE/etc/profile
groupadd --system guixbuild
for i in `seq -w 1 10`;
do
   useradd -g guixbuild -G guixbuild         \
           -d /var/empty -s `which nologin`  \
           -c "Guix build user $i" --system  \
           guixbuilder$i;
done;

cp ~root/.config/guix/current/lib/systemd/system/guix-daemon.service /etc/systemd/system/
systemctl start guix-daemon && systemctl enable guix-daemon
mkdir -p /usr/local/bin
cd /usr/local/bin
ln -s /var/guix/profiles/per-user/root/current-guix/bin/guix
mkdir -p /usr/local/share/info
cd /usr/local/share/info
for i in /var/guix/profiles/per-user/root/current-guix/share/info/*; do
    ln -s $i; done
guix archive --authorize < ~root/.config/guix/current/share/guix/ci.guix.gnu.org.pub
# guix pull
guix package -i glibc-utf8-locales
export GUIX_LOCPATH="$HOME/.guix-profile/lib/locale"
guix package -i openssl

function write_server_config() {
cat >> $CONFIG <<EOL
;; Server Configuration (plain) v1
;; /etc/system.scm

(use-modules (gnu))
(use-service-modules networking ssh)
(use-package-modules screen ssh certs tls)

(operating-system
  (host-name "${HOSTNAME}")
  (timezone "${TIMEZONE}")
  (locale "${LOCALE}")

  (initrd-modules (append (list "virtio_scsi")
                                %base-initrd-modules))

  (bootloader (bootloader-configuration
               (bootloader grub-bootloader)
               (target "/dev/sda")))
       
  (file-systems (append
        (list (file-system
                (device "/dev/sda1")
                (mount-point "/")
                (type "ext4")))
              %base-file-systems))

  (users (cons (user-account
                (name "${USERNAME}")
                (comment "${USER_COMMENT}")
                (group "users")
		        (password (crypt "${USER_PASSWORD}" "${CRYPT}"))

                (supplementary-groups '("wheel"))
                (home-directory "/home/${USERNAME}"))
               %base-user-accounts))

  ;; Globally-installed packages.
  (packages (cons* screen openssh nss-certs gnutls %base-packages))

  (services (cons* 
  (service dhcp-client-service-type)
  (service openssh-service-type
  		  (openssh-configuration
		  (permit-root-login 'without-password)))
  %base-services)))
EOL
}

function write_system_channels() {
cat >> $CHANNELS <<EOL
;; PantherX Default Channels

(list (channel
        (name 'guix)
        (url "https://channels.pantherx.org/git/pantherx.git")
        (branch "rolling-nonlibre"))
      (channel
        (name 'nongnu)
        (url "https://channels.pantherx.org/git/nongnu.git")
        (branch "rolling"))
      (channel
        (name 'pantherx)
        (url "https://channels.pantherx.org/git/pantherx-extra.git")
        (branch "master")))
EOL
}

write_server_config
write_system_channels
#write_signing_key
# guix archive --authorize < /etc/packages.pantherx.org.pub
# guix pull --disable-authentication --channels=/etc/channels.scm
# hash guix

guix system build /etc/bootstrap-config.scm
# these appear to be the necessary on Ubuntu 21.04
mv /etc/ssl /etc/bk_ssl
mv /etc/pam.d /etc/bk_pam.d
mv /etc/skel /etc/bk_skel

guix system reconfigure /etc/bootstrap-config.scm
mv /etc /old-etc
mkdir /etc
cp -r /old-etc/{passwd,group,shadow,gshadow,mtab,guix,bootstrap-config.scm} /etc/
cp /old-etc/channels.scm /etc/guix/channels.scm
guix system reconfigure /etc/bootstrap-config.scm

echo "We are done here."
echo $HOSTNAME

# reboot

2. Reconfigure to include PantherX Channels

#!/bin/bash

# PantherX on Hetzner
# Script 2/2

# THIS IS OPTIONAL
# If you just want to deploy to the target machine, you don't need to run this script.

###### MODIFY

TIMEZONE="Europe/Berlin"
LOCALE="en_US.utf8"
USERNAME="panther"
USER_COMMENT="panther's account"
USER_PASSWORD="6a4NQqrp84Y7mj56"

###### MODIFY END

if [ "$USER_PASSWORD" == "6a4NQqrp84Y7mj56" ]; then
	echo "######### IMPORTANT #########"
	echo "You did not modify the default user password. Overwriting ..."
	USER_PASSWORD=$(openssl rand -base64 24)
	echo
	echo "#########"
	echo $USER_PASSWORD
	echo "#########"
	echo
fi

CONFIG_INSTALL=/etc/bootstrap-config.scm
CONFIG=/etc/system.scm
CRYPT='$6$abc'

function write_server_config() {
cat >> $CONFIG <<EOL
;; PantherX OS Server Configuration r2 modified
;; boot on DigitalOcean
;; /etc/system.scm

(use-modules (gnu)
	     (gnu system)
	     (px system)
	     (gnu packages networking)
	     (px system install)
	     (srfi srfi-1)
	     (gnu packages))

(use-service-modules networking ssh)

(define %custom-nftables-ruleset
  (plain-file "nftables.conf"
	      "
flush ruleset

table inet filter {
chain input {
type filter hook input priority 0; policy drop;

# early drop of invalid connections
ct state invalid drop

# allow established/related connections
ct state { established, related } accept

# allow from loopback
iifname lo accept

# allow icmp
ip protocol icmp accept
ip6 nexthdr icmpv6 accept

# allow ssh, http, https
tcp dport { ssh, http, https } accept

# reject everything else
reject with icmpx type port-unreachable
}
chain forward {
type filter hook forward priority 0; policy drop;
}
chain output {
type filter hook output priority 0; policy accept;
}
}
"))

(define %ssh-public-key
  "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIP7gcLZzs2JiEx2kWCc8lTHOC0Gqpgcudv0QVJ4QydPg franz")

(remove! (lambda (service)
	   (eq? (service-kind service) 
		dhcp-client-service-type)) 
	 %px-server-services)

(define %custom-server-services
  (modify-services %px-server-services
		   (openssh-service-type
		    config =>
		    (openssh-configuration
		     (inherit config)
		     (authorized-keys
		      <ACCENT>(("root" ,(plain-file "panther.pub"
					     %ssh-public-key))))))
		   (nftables-service-type
		    config =>
		    (nftables-configuration
		     (inherit config)
		     (ruleset %custom-nftables-ruleset)))))

(px-server-os
 (operating-system
  (host-name "guix-testing")
  (timezone "Europe/Berlin")
  (locale "en_US.utf8")
  
  (initrd-modules (append (list "virtio_scsi")
                          %base-initrd-modules))
  
  (bootloader (bootloader-configuration
               (bootloader grub-bootloader)
               (target "/dev/sda")))
  
  (file-systems (append
		 (list (file-system
			(device "/dev/sda1")
			(mount-point "/")
			(type "ext4")))
		 %base-file-systems))
  
  (users (cons (user-account
		(name "${USERNAME}")
		(comment "${USER_COMMENT}")
		(group "users")
		(password (crypt "${USER_PASSWORD}" "${CRYPT}"))
		
		(supplementary-groups '("wheel"))
		(home-directory "/home/${USERNAME}"))
	       %base-user-accounts))
  
  ;; Globally-installed packages.
  (packages (cons* %px-server-packages))
  
  (services (cons* (service dhcp-client-service-type)
		   %custom-server-services))))
EOL
}

write_server_config
sed -i "s/<ACCENT>/\`/" $CONFIG

guix pull --disable-authentication --channels=/etc/guix/channels.scm

hash guix
guix system reconfigure $CONFIG

# Cleanup
rm /etc/bootstrap-config.scm
rm -rf /old-etc

reboot