Server Installation

Contents

Preliminaries

Pre-installation

  1. Download the Fedora IoT .iso installer. In the unlikely scenario that your hosting provider offers Fedora IoT images, you can skip until step 4.

  2. Upload and attach the .iso installer to the virtual machine.

  3. Configure the VM for UEFI boot.

  4. Set the following DNS records:

    The CAA records make sure that only Let's Encrypt and ZeroSSL can issue certificates for the domain, and the HTTPS records can sometimes speed up the initial connection times.

    Type Hostname Value
    A 152.53.36.213
    AAAA 2a0a:4cc0:2000:172::1
    HTTPS 1 . alpn="h3,h2" ipv4hint="152.53.36.213" ipv6hint="2a0a:4cc0:2000:172::1"
    CNAME www maxchernoff.ca.
    CNAME overleaf maxchernoff.ca.
    CNAME woodpecker maxchernoff.ca.
    CAA 0 issue "letsencrypt.org"
    CAA 0 issue "sectigo.com"
    CAA 0 issuewild ";"

Installation

  1. Start the installer.

  2. Disable the root account and create an administrator max.

  3. Partition as follows:

    Index Mount Point Size Type
    1 /boot/efi 500M EFI
    2 /boot 4G ext4
    3 [SWAP] 8G swap
    4 / remaining btrfs
    4.1 /home/ subvol
  4. Install the system.

  5. Reboot into the installed system.

  6. Install your SSH key:

    % ssh-copy-id max@maxchernoff.ca  # From your local machine
    
  7. Log in to the server:

    % ssh max@maxchernoff.ca
    
  8. Enable IPv6:

    $ sudo nmcli connection modify ens3 ipv6.method manual ipv6.addresses 2a0a:4cc0:2000:172::1/64 ipv6.gateway fe80::1
    $ sudo nmcli connection up ens3
    
  9. Reboot.

    $ sudo systemctl reboot
    

Post-installation

  1. Install the needed packages:

    $ sudo rpm-ostree install borgbackup btrfs-progs fail2ban fish git goaccess htop snapper stow vim
    
  2. Switch shell to fish:

    $ chsh -s /usr/bin/fish
    
  3. Fix /etc/fstab:

    Change the options for / to defaults,compress=zstd:1.

  4. Fix /etc/passwd: If not done, podman will complain about a mismatched home location.

    Change the home for max to /var/home/max.

  5. Adjust your home directory permissions: Needed for the unprivileged containers to access the Git files.

    $ chmod -R g-rX,o-rX ~
    $ chmod a+X ~
    

Installing TeX Live

  1. Create the tex user:

    $ sudo useradd --create-home --shell /usr/sbin/nologin tex
    $ sudo loginctl enable-linger tex
    
  2. Switch to the tex user:

    $ sudo -u tex fish
    
  3. Create the necessary directories:

    % mkdir -p ~/texlive  # As the `tex` user
    
  4. Download the installer:

    % cd $(mktemp -d)
    % curl -O 'https://ftp.math.utah.edu/pub/ctan/tex-archive/systems/texlive/tlnet/install-tl-unx.tar.gz'
    % tar xf install-tl-unx.tar.gz
    
  5. Install TeX Live:

    % ./install-tl-*/install-tl \
    >     --repository=https://ftp.math.utah.edu/pub/ctan/tex-archive/systems/texlive/tlnet \
    >     --texdir=/var/home/tex/texlive --scheme=full --paper=letter
    
  6. Set the Unix permissions:

    % chmod -R g-rX,o-rX ~
    % chmod a+X ~
    % chmod -R a+rX ~/texlive
    
  7. Add the SELinux rules: Needed for the containers to be able to access the TeX Live installation.

    $ sudo semanage fcontext --add -t container_ro_file_t '/var/home/tex/texlive(/.*)?'
    $ sudo restorecon -R /var/home/tex/texlive
    

Web Server

  1. Generate a new SSH key:

    $ ssh-keygen -t ed25519
    
  2. Add this new key as a single-repo deploy key on GitHub.

  3. Clone the repository:

    $ git clone git@github.com:gucci-on-fleek/maxchernoff.ca.git
    
  4. Set the Unix permissions:

    $ chmod -R a+rX /var/home/max/maxchernoff.ca/web
    $ chmod -R a=,u=rwX /var/home/max/maxchernoff.ca/.git
    
  5. Create the web user:

    $ sudo useradd --create-home --shell /usr/sbin/nologin web
    
  6. Allow the web user to run services:

    $ sudo loginctl enable-linger web
    
  7. Switch to the web user:

    $ sudo -u web fish
    
  8. Set the Unix permissions:

    % chmod -R g-rX,o-rX ~  # As the `web` user
    % chmod a+X ~
    
  9. Enable the analytics processor:

    $ sudo touch ~web/caddy/access.log
    $ sudo chown $uid:web ~web/caddy/access.log
    $ sudo chmod a=,ug=rw ~web/caddy/access.log
    
    $ touch ~/maxchernoff.ca/web/caddy/static/analytics/{graphs,requests.tsv}
    $ chmod -R a=rX,ug=rwX ~/maxchernoff.ca/web/caddy/static/analytics
    $ chmod g+s ~/maxchernoff.ca/web/caddy/static/analytics
    $ sudo chgrp -R web ~/maxchernoff.ca/web/caddy/static/analytics
    
  10. Start the services:

    $ sudo systemctl --user -M web@ start overleaf-pod.service caddy.service
    
  11. Reboot to make sure everything starts correctly.

Woodpecker CI

  1. Switch to the web user:

    $ sudo -u web fish
    
  2. Add the Woodpecker server Podman secrets:

    % cat | tr -d '\n' | \ # Paste the secret, Enter, Ctrl+D
    >     podman secret create woodpecker_github_secret -
    % head --bytes=36 /dev/urandom | basenc --z85 | tr -d '\n' | \
    >     tee /dev/stderr | \ # Copy this value for later
    >     podman secret create woodpecker_agent_secret -
    
  3. Create the woodpecker user:

    $ sudo useradd --create-home --shell /usr/sbin/nologin woodpecker
    $ sudo loginctl enable-linger woodpecker
    
  4. Switch to the woodpecker user:

    $ sudo -u woodpecker fish
    
  5. Set the Unix permissions:

    % chmod -R g-rX,o-rX ~  # As the `woodpecker` user
    % chmod a+X ~
    
  6. Add the Woodpecker agent Podman secrets:

    % cat | tr -d '\n' | \ # Paste the secret, Enter, Ctrl+D
    >     podman secret create woodpecker_agent_secret -
    
  7. Start the services:

    $ sudo systemctl --user -M web@ daemon-reload
    $ sudo systemctl --user -M web@ start woodpecker-server.service
    
    $ sudo systemctl --user -M woodpecker@ daemon-reload
    $ sudo systemctl --user -M woodpecker@ start woodpecker-agent.service
    

Snapshots

  1. Mount the snapshot directory:

    # /etc/fstab
    # This line was here originally
    UUID={uuid}  /home/            btrfs  subvol={subvol},compress=zstd:1             0  0
    # Add this line
    UUID={uuid}  /home/.snapshots  btrfs  subvol={subvol}/.snapshots,compress=zstd:1  0  0
    
    $ sudo systemctl daemon-reload
    $ sudo mount -av