diff --git a/src/consts.ts b/src/consts.ts
new file mode 100644
index 0000000..60718a7
--- /dev/null
+++ b/src/consts.ts
@@ -0,0 +1,9 @@
+import type { Metadata, Site } from "@types";
+export const SITE: Site = {
+ TITLE: "z0x",
+ DESCRIPTION: "z0x's blog",
+};
+export const HOME: Metadata = {
+ TITLE: "blog",
+};
+
diff --git a/src/content.config.ts b/src/content.config.ts
new file mode 100644
index 0000000..6163f73
--- /dev/null
+++ b/src/content.config.ts
@@ -0,0 +1,14 @@
+import { defineCollection, z } from "astro:content";
+import { glob } from 'astro/loaders';
+
+const blog = defineCollection({
+ loader: glob({ pattern: '**/*.{md,mdx}', base: "./src/content" }),
+ schema: z.object({
+ title: z.string(),
+ description: z.string(),
+ date: z.coerce.date(),
+ draft: z.boolean().optional(),
+ }),
+});
+
+export const collections = { blog };
diff --git a/src/content/artix-install-guide/index.md b/src/content/artix-install-guide/index.md
new file mode 100644
index 0000000..8c379a2
--- /dev/null
+++ b/src/content/artix-install-guide/index.md
@@ -0,0 +1,644 @@
+---
+title: "Artix Linux install guide"
+description: "Guide to installing Artix Linux with OpenRC and full disk encryption for UEFI and BIOS systems."
+date: "2025-01-07"
+---
+---
+
+## Introduction
+
+The goal of this guide is to set up a minimal installation of **Artix Linux** with **OpenRC** as an init system and **full disk encryption** on an **UEFI** or **BIOS** system. This guide is meant to be read alongside the wiki's.
+
+---
+
+## Acquire an installation image
+
+1. Go to the downloads page https://artixlinux.org/download.php
+2. Scroll down to the **Official ISO images** section.
+3. Under the **base** section, download the file starting with `artix-base-openrc` and ending with `.iso`
+
+---
+
+## Prepare an installation medium
+
+### Windows
+
+Use [Rufus](https://rufus.ie/en), here is a [guide](https://www.wikihow.com/Use-Rufus) if you need it.
+
+### Linux
+
+1. Insert a USB flash drive into your PC with at least 2 GB of space available on it.
+2. Find the corresponding block device for the flash drive in `/dev` folder. Usually it is `/dev/sdb`.
+3. Burn the image to the flash drive (assuming your flash drive is /dev/sdb and that your terminal is opened in the directory of the image)
+
+```
+sudo dd bs=4M if=./artix-base-openrc-YYYY.MM.DD-x86_64.iso of=/dev/sdb conv=fsync oflag=direct status=progress
+```
+
+---
+
+## Boot the live environment
+
+> [!Info]
+>Artix Linux installation images do not support Secure Boot. You will need to disable Secure Boot to boot the installation medium.
+
+1. Power off your PC.
+2. Insert the flash drive into the computer on which you are installing Artix Linux.
+3. Power on your PC and press _boot menu_ key.
+4. Boot the installation medium.
+
+---
+
+## Enter the live environment
+1. Login with the default credentials.
+* Username: `artix`
+* Password: `artix`
+
+2. Switch to the root user
+
+> [!Note]
+>When encountering a code block as below throughout this guide, execute the commands within it directly in the terminal.
+
+> [!Info]
+>When prompted for a password, enter `artix`
+
+```
+su -
+```
+
+---
+
+## Connect to the internet
+
+### Via Ethernet
+
+Connect the computer via an Ethernet cable
+
+### Via WiFi
+
+```
+sudo rfkill unblock wifi
+sudo ip link set wlan0 up
+connmanctl
+```
+
+> [!Tip]
+>Network names can be tab-completed.
+
+```
+agent on
+scan wifi
+services
+```
+
+> [!example]
+>connect wifi_dc85de828967_38303944616e69656c73_managed_psk
+
+```
+connect {WiFi name}
+quit
+```
+
+### Verify internet connectivity
+
+Check for internet
+```
+ping artixlinux.org
+```
+
+---
+
+## Update the system clock
+
+Activate the NTP daemon to synchronize the computer's real-time clock:
+```
+rc-service ntpd start
+```
+
+---
+
+## Partition the disk
+
+1. Install `gdisk`.
+```
+pacman -Sy gdisk
+```
+
+2. Partition your drive. You can find your drive name using the `lsblk` command.
+
+> [!Note]
+> I will be using `nvme0n1` as my drive throughout this guide, please adapt it to your disk name.
+> If you have an hdd, your drive name may ressemble something like `sda`.
+
+```
+gdisk /dev/nvme0n1
+```
+
+2. Delete any existing partitions
+```
+Command (m for help): d
+```
+
+3. Create a boot partition
+```
+Command (m for help): n
+Partition number (1-128, default 1):
+First sector (...):
+Last sector (...): +512M
+Hex code or GUID (...): ef00
+```
+
+4. Create a root partition
+```
+Command (m for help): n
+Partition number (2-128, default 1):
+First sector (...):
+Last sector (...):
+Hex code or GUID (...): 8300
+```
+
+5. Save the changes
+```
+Command (m for help): w
+Do you want to proceed? (Y/N): y
+```
+
+6. Verify partitioning
+```
+lsblk
+```
+
+> [!Note]
+>It should look something like this:
+
+```
+NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
+nvme0n1 259:0 0 465,8G 0 disk
+├─nvme0n1p1 259:1 0 512M 0 part
+└─nvme0n1p2 259:2 0 465,3G 0 part
+```
+
+---
+
+## Encrypt root partition
+
+1. Encrypt your root partition.
+
+> [!Tip]
+>Make sure to to enter a secure passphrase and to write it down in a secure place as you will not be able to change it later
+
+```
+cryptsetup luksFormat /dev/nvme0n1p2
+Are you sure (Type `yes` in capital letters): YES
+```
+
+2. Open the encrypted partition
+```
+cryptsetup open /dev/nvme0n1p2 root
+```
+
+---
+
+## Create file systems
+
+1. Create the boot file system
+```
+mkfs.fat -F32 /dev/nvme0n1p1
+```
+
+1. Create the root file system
+```
+mkfs.ext4 /dev/mapper/root
+```
+
+---
+
+## Mount file systems
+
+1. Mount the root file system
+```
+mount /dev/mapper/root /mnt
+```
+
+2. Mount the boot file system
+```
+mount -m /dev/nvme0n1p1 /mnt/boot
+```
+
+3. Verify mounting
+```
+lsblk
+```
+
+> [!Note]
+>It should look something like this:
+
+```
+NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
+nvme0n1 259:0 0 465,8G 0 disk
+├─nvme0n1p1 259:1 0 512M 0 part /mnt/boot
+└─nvme0n1p2 259:2 0 465,3G 0 part
+ └─root 254:0 0 465,2G 0 crypt /mnt
+```
+
+---
+
+## Install Essentials
+
+Install the base system, kernel, init system and other essential packages.
+
+```
+basestrap /mnt base linux linux-firmware openrc elogind-openrc cryptsetup cryptsetup-openrc efibootmgr doas nano
+```
+
+> [!Note]
+> Install AMD or Intel microcode, depending on your system's CPU
+
+### AMD CPU
+
+Install AMD CPU microcode updates
+
+```
+basestrap /mnt amd-ucode
+```
+
+### Intel CPU
+
+Install Intel CPU microcode updates
+
+```
+basestrap /mnt intel-ucode
+```
+
+### Network stack
+
+```
+basestrap /mnt wpa_supplicant networkmanager networkmanager-openrc iwd iwd-openrc
+rc-update add NetworkManager
+rc-update add iwd
+
+cat << EOF >> /etc/NetworkManager/conf.d/wifi_backend.conf
+[device]
+wifi.backend=iwd
+EOF
+```
+
+#### MAC randomization
+
+> [!Info]
+>MAC randomization can be used for increased privacy by not disclosing your real MAC address to the WiFi network.
+
+```
+cat << EOF >> /etc/NetworkManager/conf.d/00-macrandomize.conf
+[device-mac-randomization]
+wifi.scan-rand-mac-address=yes
+
+[connection-mac-randomization]
+ethernet.cloned-mac-address=random
+wifi.cloned-mac-address=random
+EOF
+```
+
+---
+
+## Generate File System Table
+
+```
+fstabgen -U /mnt >> /mnt/etc/fstab
+```
+
+---
+
+## Switch to New Installation
+
+```
+artix-chroot /mnt bash
+```
+
+---
+
+## Localization
+
+### Set the locale
+
+> [!Note]
+>Feel free to change `en_DK.UTF-8` to your preferred locale such as `en_US.UTF-8` or `en_GB.UTF-8`
+
+1. Un-comment `en_DK.UTF-8`
+```
+nano /etc/locale.gen
+```
+
+2. Generate locales.
+```
+locale-gen
+echo 'LANG=en_DK.UTF-8' > /etc/locale.conf
+```
+
+---
+
+## Set the time zone
+
+> [!example]
+>`ln -sf /usr/share/zoneinfo/America/Toronto /etc/localtime`
+
+```
+ln -sf /usr/share/zoneinfo/Region/City /etc/localtime
+```
+
+---
+
+## Set hardware clock from system clock
+
+```
+hwclock --systohc
+```
+
+---
+
+## Hostname and Host
+
+> [!Note]
+>Change `artix` to your desired hostname in all of the following commands
+
+```
+echo 'artix' > /etc/hostname
+```
+
+1. Edit `/etc/conf.d/hostname`
+```
+nano /etc/conf.d/hostname
+```
+
+2. Replace `hostname="localhost"` with `hostname="artix"`
+
+3. Edit `/etc/hosts`
+```
+nano /etc/hosts
+```
+
+4. Add the following:
+```
+127.0.0.1 localhost
+::1 localhost
+127.0.1.1 artix.localdomain artix
+```
+
+---
+
+## Initramfs
+
+1. Edit `/etc/mkinitcpio.conf`
+```
+nano /etc/mkinitcpio.conf
+```
+
+2. In the `HOOKS` array, add `encrypt` between `block` and `filesystems`
+```
+mkinitcpio -P
+```
+
+> [!Note]
+>It should look something like this:
+
+```
+HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block encrypt filesystems fsck)
+```
+
+---
+
+## Add a user
+
+1. Set the root password.
+```
+passwd
+```
+
+2. Create a user and set his password.
+
+> [!Tip]
+>Change `artix` to your desired username
+
+```
+useradd -m artix
+passwd artix
+```
+
+---
+
+## Configure doas
+
+1. Create the config file.
+```
+touch /etc/doas.conf
+chown -c root:root /etc/doas.conf
+chmod -c 0400 /etc/doas.conf
+```
+
+2. Edit `/etc/doas.conf`
+```
+nano /etc/doas.conf
+```
+
+3. Add the following:
+```
+permit artix as root
+permit nopass artix as root cmd pacman
+```
+
+---
+
+## Boot Loader
+### Check for UEFI support
+
+> [!Tip]
+>If you see a bunch of files listed, use EFISTUB.
+>If you do not see a bunch of files listed, your system does not support UEFI and you should use GRUB.
+
+```
+ls /sys/firmware/efi/efivars
+```
+
+### EFISTUB
+
+1. Get the UUID of your root partition.
+```
+blkid -s UUID -o value /dev/nvme0n1p2
+```
+
+2. Create a boot entry
+
+> [!Tip]
+>Replace xxxx with the UUID that you obtained earlier.
+>Replace `intel-ucode.img` with `amd-ucode.img` if you have an AMD CPU
+
+```
+efibootmgr -c -d /dev/nvme0n1 -p 1 -l /vmlinuz-linux -L "Artix" -u "cryptdevice=UUID=xxxx:root root=/dev/mapper/root rw initrd=\intel-ucode.img initrd=\initramfs-linux.img loglevel=3 quiet"
+```
+
+### GRUB
+
+1. Install grub on your boot partition
+```
+pacman -S grub
+grub-install /dev/sda
+```
+
+2. Get the UUID of your root partition.
+```
+blkid -s UUID -o value /dev/nvme0n1p2
+```
+
+3. Edit `/etc/default/grub`
+```
+nano /etc/default/grub
+```
+
+4. Add the following to the `GRUB_CMDLINE_LINUX` line, where xxxx is the UUID that you obtained earlier.
+```
+cryptdevice=UUID=xxxx:root root=/dev/mapper/root
+```
+
+> [!Note]
+>It should look something like this:
+
+```
+GRUB_CMDLINE_LINUX="cryptdevice=UUID=550e8400-e29b-41d4-a716-446655440000:root root=/dev/mapper/root"
+```
+
+5. Un-comment `#GRUB_ENABLE_CRYPTODISK=y`
+
+6. Generate the config file.
+```
+grub-mkconfig -o /boot/grub/grub.cfg
+```
+
+---
+
+## Reboot
+
+1. You can reboot and enter into your new installation.
+```
+exit
+umount -R /mnt
+reboot now
+```
+
+> [!Note]
+>Unplug your flash drive after the screen turns black.
+
+---
+
+## Post install
+
+You will now be greeted with a similar screen as when you first booted from the flash drive.
+Login using the credentials that you set, if you followed the example your username would be `artix`.
+
+### Add arch repositories and sort for fastest mirrors
+#### Add arch extra repository
+
+1. Install packages
+```
+doas pacman -Syu artix-archlinux-support curl
+doas pacman-key --populate archlinux
+doas sh -c "curl https://archlinux.org/mirrorlist/all -o /etc/pacman.d/mirrorlist-arch"
+```
+
+2. Edit `/etc/pacman.d/mirrorlist-arch`
+```
+doas nano /etc/pacman.d/mirrorlist-arch
+```
+
+3. Un-comment the first server entries under the worldwide section
+
+4. Edit `/etc/pacman.conf`
+```
+doas nano /etc/pacman.conf
+```
+
+5. Add the following to the bottom of the file
+```
+##Arch
+[extra]
+Include = /etc/pacman.d/mirrorlist-arch
+
+##[multilib]
+##Include = /etc/pacman.d/mirrorlist-arch
+```
+
+#### Sort for fastest mirrors
+
+```
+doas pacman -Syu reflector pacman-contrib
+doas reflector --verbose -p https -l 30 -f 5 --sort rate --save /etc/pacman.d/mirrorlist-arch
+doas sh -c "curl https://gitea.artixlinux.org/packages/artix-mirrorlist/raw/branch/master/mirrorlist -o /etc/pacman.d/mirrorlist.bak"
+doas sh -c "rankmirrors -v -n 5 /etc/pacman.d/mirrorlist.bak > /etc/pacman.d/mirrorlist"
+```
+
+### AUR
+#### Install Paru
+
+```
+doas pacman -S --needed base-devel
+git clone https://aur.archlinux.org/paru.git
+cd paru
+makepkg -si
+cd ..
+rm -rf paru
+```
+
+#### Replace sudo with doas
+
+```
+doas pacman -Rdd sudo
+doas ln -s /usr/bin/doas /usr/bin/sudo
+```
+
+### Laptop power profiles
+
+Install and enable the powerprofiles daemon
+
+```
+doas pacman -S power-profiles-daemon power-profiles-daemon-openrc
+doas rc-update add power-profiles-daemon
+doas rc-service power-profiles-daemon start
+```
+
+### Add swap
+
+```
+doas fallocate -l 4G /swapfile
+doas chmod 600 /swapfile
+daos mkswap /swapfile
+doas swapon /swapfile
+doas cp /etc/fstab /etc/fstab.bak
+echo '/swapfile none swap sw 0 0' | doas tee -a /etc/fstab
+```
+
+### Auto-mount an external LUKS encrypted drive
+
+```
+doas fdisk /dev/sdb
+>g, n, w
+
+doas cryptsetup luksFormat /dev/sdb1
+doas cryptsetup luksOpen /dev/sdb1 hdd1
+doas mkfs.ext4 /dev/mapper/hdd1
+doas mkdir /mnt/hdd1
+doas mount /dev/mapper/hdd1 /mnt/hdd1
+doas chown vega:vega /mnt/hdd1
+doas dd if=/dev/urandom of=/root/keyfile_hdd1 bs=512 count=4
+doas chmod 0400 /root/keyfile_hdd1
+doas cryptsetup luksAddKey /dev/sdb1 /root/keyfile_hdd1
+UUID=$(doas blkid -s UUID -o value /dev/sdb1)
+
+doas sh -c "cat << EOF >> /etc/conf.d/dmcrypt
+target=hdd1
+source=UUID='$UUID'
+key=/root/keyfile_hdd1
+wait=2
+EOF"
+
+doas rc-update add dmcrypt boot
+doas reboot
+```
\ No newline at end of file
diff --git a/src/favicon.svg b/src/favicon.svg
new file mode 100644
index 0000000..63d5f6d
--- /dev/null
+++ b/src/favicon.svg
@@ -0,0 +1,55 @@
+
+
diff --git a/src/layouts/Layout.astro b/src/layouts/Layout.astro
new file mode 100644
index 0000000..a4d8bcc
--- /dev/null
+++ b/src/layouts/Layout.astro
@@ -0,0 +1,24 @@
+---
+import Head from "@components/Head.astro";
+import Footer from "@components/Footer.astro";
+import { SITE } from "@consts";
+
+type Props = {
+ title: string;
+ description: string;
+};
+
+const { title, description } = Astro.props;
+---
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/lib/utils.ts b/src/lib/utils.ts
new file mode 100644
index 0000000..294b335
--- /dev/null
+++ b/src/lib/utils.ts
@@ -0,0 +1,13 @@
+import { clsx, type ClassValue } from "clsx";
+import { twMerge } from "tailwind-merge";
+
+export function cn(...inputs: ClassValue[]) {
+ return twMerge(clsx(inputs));
+}
+
+export function readingTime(html: string) {
+ const textOnly = html.replace(/<[^>]+>/g, "");
+ const wordCount = textOnly.split(/\s+/).length;
+ const readingTimeMinutes = (wordCount / 200 + 1).toFixed();
+ return `${readingTimeMinutes} min read`;
+}
diff --git a/src/pages/404.astro b/src/pages/404.astro
new file mode 100644
index 0000000..04dd251
--- /dev/null
+++ b/src/pages/404.astro
@@ -0,0 +1,13 @@
+---
+import Layout from "@layouts/Layout.astro";
+import Container from "@components/Container.astro";
+import { SITE } from "@consts";
+---
+
+
+
+
+
404: Page not found
+
+
+
diff --git a/src/pages/[...id].astro b/src/pages/[...id].astro
new file mode 100644
index 0000000..4ed3241
--- /dev/null
+++ b/src/pages/[...id].astro
@@ -0,0 +1,68 @@
+---
+import { type CollectionEntry, getCollection, render } from "astro:content";
+import Layout from "@layouts/Layout.astro";
+import Container from "@components/Container.astro";
+import FormattedDate from "@components/FormattedDate.astro";
+import { readingTime } from "@lib/utils";
+import PostNavigation from "@components/PostNavigation.astro";
+import TableOfContents from "@components/TableOfContents.astro";
+
+export async function getStaticPaths() {
+ const posts = (await getCollection("blog")).filter((post) => !post.data.draft).sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf());
+ return posts.map((post) => ({
+ params: { id: post.id },
+ props: post,
+ }));
+}
+type Props = CollectionEntry<"blog">;
+
+const posts = (await getCollection("blog")).filter((post) => !post.data.draft).sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf());
+
+function getNextPost() {
+ let postIndex;
+ for (const post of posts) {
+ if (post.id === Astro.params.id) {
+ postIndex = posts.indexOf(post);
+ return posts[postIndex + 1];
+ }
+ }
+}
+
+function getPrevPost() {
+ let postIndex;
+ for (const post of posts) {
+ if (post.id === Astro.params.id) {
+ postIndex = posts.indexOf(post);
+ return posts[postIndex - 1];
+ }
+ }
+}
+
+const nextPost = getNextPost();
+const prevPost = getPrevPost();
+
+const post = Astro.props;
+const { Content, headings } = await render(post);
+---
+
+
+
+