podbox/AlmaLinux.md
2025-02-08 16:14:24 -06:00

256 lines
6 KiB
Markdown

# AlmaLinux
My proof of concept server running this container stack is built on AlmaLinux
9.4.
> [!WARNING]
> Perform `dnf update` immediately
## [Repositories](https://wiki.almalinux.org/repos/)
These may not really be necessary to set up, but you should absolutely review
them and decide for yourself.
- [AlmaLinux](https://wiki.almalinux.org/repos/AlmaLinux.html)
- [CentOS SIGs](https://wiki.almalinux.org/repos/CentOS.html)
- [Extra](https://wiki.almalinux.org/repos/Extras.html)
- EPEL and CRB
- `dnf install epel-release`
- `dnf config-manager --set-enabled crb`
- ELRepo
- `dnf install elrepo-release`
- [RPM Fusion](https://wiki.almalinux.org/documentation/epel-and-rpmfusion.html)
## Disks
### Partitions
Repeat the following steps for all disks that you want to join together into
one single logical volume.
```bash
# Find /dev/sdX paths for disks
# WARNING: Make sure you confirm the disk is correct
lsblk -f
# Clear the partition table
dd if=/dev/zero of=/dev/sdX bs=512 count=1 conv=notrunc
dd if=/dev/zero of=/dev/sdY bs=512 count=1 conv=notrunc
```
### LVM
```bash
# Create physical volume
pvcreate /dev/sdX
# Create volume group for disks
vgcreate library /dev/sdX
# Add more disks to volume group
vgextend library /dev/sdY
# Create logical volume across all disks in volume group
lvcreate -l100%FREE -n books library
# Add filesystem to logical volume
mke2fs -t ext4 /dev/library/books
# Check it
e2fsck -f /dev/library/books
```
### /etc/systemd/system/volumes-books.mount
```ini
[Mount]
What=/dev/library/books
Where=/volumes/books
Type=ext4
[Install]
WantedBy=default.target
```
> [!NOTE]
> We could use a different filesystem that allows mount options to set the
> permissions
```bash
chown -R $ctuser:$ctuser /volumes
```
## SSH
SSH is optional, but highly encouraged. Cockpit gives you a terminal too, but
that's nowhere near as good as what you can do with a real terminal emulator
and ssh clients.
```bash
dnf install openssh-server
## Generate strong key on your laptop or workstation/desktop
ssh-keygen -t ed25519 -a 32 -f ~/.ssh/$localhost-to-$remotehost
## Copy key to AlmaLinux
ssh-copy-id -i ~/.ssh/$localhost-to-$remotehost $user@$remotehost
```
## Override `sshd` config
We don't want to allow anyone to login as root remotely ever. You must be a
`sudoer` with public key auth to elevate to root.
```bash
printf '%s\n' 'PermitRootLogin no' > /etc/ssh/sshd_config.d/01-root.conf
printf '%s\n' \
'PubkeyAuthentication yes' \
'PasswordAuthentication no' > /etc/ssh/sshd_config.d/01-pubkey.conf
```
## Cockpit -> https://ip-addr:9090
> [!WARNING]
> I run behind an existing firewall, not in a VPS or cloud provider.
> ```bash
> systemctl disable --now firewalld
> ```
> [!NOTE]
> Should be able to set up good firewall with only 22/80/443 open.
Enable the socket-activated cockpit service and allow it through the firewall.
```bash
systemctl enable --now cockpit.socket
# FIXME: Unnecessary? Default works?
firewall-cmd --permanent --zone=public --add-service=cockpit
firewall-cmd --reload
```
## Add SSH keys
> [!TIP]
> Skip if you copied your keys with `ssh-copy-id` above.
`Accounts` -> `Your account` -> `Authorized public SSH keys` -> `Add Key`
## Install SELinux troubleshoot tool
This is a component for Cockpit.
```bash
dnf install setroubleshoot-server
```
## Podman
Podman is a daemonless container hypervisor. This document prepares a fully
rootless environment for our containers to run in.
## Install
```bash
dnf install podman
systemctl enable --now podman
```
> [!NOTE]
> Read the docs.
> `man podman-systemd.unit`
## Prepare host networking stack
### slirp4netns
> [!NOTE]
> This may not be necessary but my system is currently using it.
```bash
dnf install slirp4netns
```
### Install DNS server for `podman`
> [!NOTE]
> Not sure how to resolve these correctly yet but the journal logs it
> so it's running for something.
```bash
dnf install aardvark-dns
```
### Allow rootless binding port 80+
> [!NOTE]
> This is only necessary if you are setting up the reverse proxy.
```bash
printf '%s\n' 'net.ipv4.ip_unprivileged_port_start=80' > /etc/sysctl.d/99-unprivileged-port-binding.conf
sysctl -w net.ipv4.ip_unprivileged_port_start=80
```
### Allow containers to route within multiple networks
```bash
printf '%s\n' 'net.ipv4.conf.all.rp_filter=2' > /etc/sysctl.d/99-reverse-path-loose.conf
sysctl -w net.ipv4.conf.all.rp_filter=2
```
## Prepare container user
This user will be the owner of all containers with no login shell or root
privileges.
```bash
# Prepare a group id outside of the normal range
groupadd --gid 2000 $ctuser
# Create user with restrictions
# We need the $HOME to live in
useradd --create-home \
--shell /usr/bin/false \
--password $ctuser_pw \
--no-user-group \
--gid $ctuser \
--groups systemd-journal \
--uid 2000 \
$ctuser
# Lock user from password login
usermod --lock $ctuser
# Add container sub-ids
usermod --add-subuids 200000-299999 --add-subgids 200000-299999 $ctuser
# Start $ctuser session at boot without login
loginctl enable-linger $ctuser
```
> [!TIP]
> Optionally setup ssh keys to directly login to $ctuser.
### Setup $ctuser env
> [!NOTE]
> The login shell doesn't exist. Launch `bash -l` manually to get a shell or
> else your `ssh` will exit with a status of 1.
```bash
# Switch to user (`-i` doesn't work without a login shell)
machinectl shell $ctuser@ /bin/bash
# Create dirs
mkdir -p ~/.config/{containers/systemd,environment.d}
# Prepare `systemd --user` env
echo 'XDG_RUNTIME_DIR=/run/user/2000' >> ~/.config/environment.d/10-xdg.conf
# Enable container auto-update
podman system migrate
# WARNING: Set strict versions for all containers or risk catastrophe
systemctl --user enable --now podman-auto-update
exit
```
> [!WARNING]
> I disabled SELinux to not deal with this for every container.
> /etc/selinux/config -> `SELINUX=disabled`
> [!TIP]
> Set up the correct policies permanently instead of disabling SELinux
Temporarily set SELinux policy to allow containers to use devices.
```bash
setsebool -P container_use_devices 1
```