Compare commits
5 commits
72ee68bea4
...
516eeed792
Author | SHA1 | Date | |
---|---|---|---|
516eeed792 | |||
99efb0470e | |||
b4de3d171b | |||
81bd613c6c | |||
880e54bde5 |
4 changed files with 841 additions and 3 deletions
|
@ -1,13 +1,13 @@
|
|||
---
|
||||
title: Alpine Linux base installation
|
||||
slug: alpine-linux-base-install
|
||||
date: 2024-08-30
|
||||
date: 2024-08-12
|
||||
draft: false
|
||||
authors:
|
||||
- luc
|
||||
- nils
|
||||
tags:
|
||||
- Alpine Linux
|
||||
- Linux
|
||||
categories:
|
||||
- Base installation
|
||||
---
|
||||
|
@ -336,4 +336,127 @@ sh# exit
|
|||
sh# umount -lf /mnt
|
||||
sh# zpool export rpool
|
||||
sh# reboot
|
||||
```
|
||||
```
|
||||
|
||||
## Post installation
|
||||
|
||||
### Repositories
|
||||
|
||||
To set the correct repositories configure:
|
||||
|
||||
``` shell title="/etc/apk/repositories"
|
||||
https://dl-cdn.alpinelinux.org/alpine/latest-stable/main
|
||||
https://dl-cdn.alpinelinux.org/alpine/latest-stable/community
|
||||
```
|
||||
|
||||
This will use the latest stable repository of Alpine (for example `v3.19`). To use a different version of Alpine simply change `latest-stable` to whatever version you want. Do note that you cannot (easily) downgrade your system's version.
|
||||
|
||||
There is also the `edge` repository which contains the latest packages, but is not recommended, due to the instability it imposes on the system.
|
||||
|
||||
> If a package is not yet in a stable release one may additionally configure:
|
||||
>
|
||||
> ``` shell title="/etc/apk/repositories"
|
||||
> @<repository> https://dl-cdn.alpinelinux.org/alpine/edge/<repository>
|
||||
> ```
|
||||
>
|
||||
> for the relevant `<repository>` and perform:
|
||||
>
|
||||
> ``` shell-session
|
||||
> sh# apk add <package>@<repository>
|
||||
> ```
|
||||
>
|
||||
> for the relevant `<package>`.
|
||||
|
||||
### Firmware and drivers
|
||||
|
||||
Install the device firmware for either AMD or Intel:
|
||||
|
||||
=== "AMD"
|
||||
|
||||
``` shell-session
|
||||
sh# apk add amd-ucode
|
||||
```
|
||||
|
||||
=== "Intel"
|
||||
|
||||
``` shell-session
|
||||
sh# apk add intel-ucode
|
||||
```
|
||||
|
||||
To make sure it is included during boot, regenerate the UKI with:
|
||||
|
||||
``` shell-session
|
||||
sh# apk fix kernel-hooks
|
||||
```
|
||||
|
||||
### Swap
|
||||
|
||||
To configure Swap install `zram-init`:
|
||||
|
||||
``` shell-session
|
||||
sh# apk add zram-init
|
||||
```
|
||||
|
||||
and add it to the default runlevel:
|
||||
|
||||
``` shell-session
|
||||
sh# rc-update add zram-init default
|
||||
```
|
||||
|
||||
Configure `zram-init` by editing:
|
||||
|
||||
``` shell title="/etc/conf.d/zram-init"
|
||||
num_devices=<n>
|
||||
|
||||
# swap - 500M
|
||||
|
||||
#size0=512
|
||||
size0=`LC_ALL=C free -m | awk '/^mem:/{print int($2/4)}'`
|
||||
```
|
||||
|
||||
Now the size of the swap device will be one fourth of the ram size.
|
||||
|
||||
### Users
|
||||
|
||||
To run applications securely, in an environment with fewer privileges, a user is necessary.
|
||||
|
||||
Before creating the user, install `doas`. To be able to "do as" root when it is required:
|
||||
|
||||
``` shell-session
|
||||
sh# apk add doas
|
||||
```
|
||||
|
||||
and configure `doas` by editing:
|
||||
|
||||
``` shell title="/etc/doas.d/wheel.conf"
|
||||
permit persist :wheel as root
|
||||
```
|
||||
|
||||
A user can be added in Alpine Linux with the `setup-user` script. Here we can specify the name, groups and more:
|
||||
|
||||
```
|
||||
# setup-user -g wheel <username>
|
||||
# passwd <username>
|
||||
```
|
||||
|
||||
You may have to change the shell of the user in `/etc/passwd` from `/sbin/nologin` to a shell from `/etc/shells`. Alpine Linux comes with `/bin/ash` by default:
|
||||
|
||||
``` shell title="/etc/passwd"
|
||||
<username>:x:1234:1234:<Full Name>:/home/<username>:/bin/<shell>
|
||||
```
|
||||
|
||||
If you have checked that `doas` works with the user then you can lock the root account because it imposes security risks if it is kept open. This can be done with:
|
||||
|
||||
```
|
||||
# passwd -l root
|
||||
```
|
||||
|
||||
and by changing its login shell to:
|
||||
|
||||
``` shell title="/etc/passwd"
|
||||
root:x:0:0:root:/root:/sbin/nologin
|
||||
```
|
||||
|
||||
## Concluding remarks
|
||||
|
||||
This is essentially it, you now have a fully operational alpine base system running, configured for server use. The next steps are the improvement of the security of the system and the configuration of the container management software.
|
349
docs/server-os/posts/02-security-improvements.md
Normal file
349
docs/server-os/posts/02-security-improvements.md
Normal file
|
@ -0,0 +1,349 @@
|
|||
---
|
||||
title: Security improvements
|
||||
slug: security-improvents
|
||||
date: 2024-08-14
|
||||
draft: true
|
||||
authors:
|
||||
- luc
|
||||
- nils
|
||||
tags:
|
||||
- Alpine Linux
|
||||
- Gentoo Linux
|
||||
categories:
|
||||
- Security
|
||||
---
|
||||
|
||||
The security of a Linux system can be further improved as will be outlined in the chapters of this blog entry. These chapters will discuss how to harden the different layers of the operating system and are based on the [Madaidans-insecurities page](https://madaidans-insecurities.github.io/guides/linux-hardening.html#kernel), various Linux man pages and the security considerations of [PlagueOS](https://0xacab.org/optout/plagueos/-/wikis/Security-Considerations) and [secureblue](https://secureblue.dev/features). Hardening the system is done to prevent as many exploits as possible. Such that in the end, you, and only you are in control of your system.
|
||||
|
||||
<!-- more -->
|
||||
|
||||
## Linux Security modules
|
||||
|
||||
Linux Security Modules (LSM) is a framework that allows the implementation of various security models in the Linux kernel.
|
||||
|
||||
These security modules may be enabled by adding them to the kernel `cmdline`:
|
||||
|
||||
``` shell title="/etc/kernel/cmdline"
|
||||
... lsm=landlock,lockdown,yama,integrity ...
|
||||
```
|
||||
|
||||
### Landlock
|
||||
|
||||
Landlock (`landlock`) is an access-control system that enables any processes to securely restrict themselves and their future children, i.e. sandboxing.
|
||||
|
||||
### Lockdown
|
||||
|
||||
Lockdown (`lockdown`) prevents both direct and indirect access to a running kernel image, attempting to protect against unauthorized modification of the kernel image and to prevent access to security and cryptographic data located in kernel memory, whilst still permitting driver modules to be loaded.
|
||||
|
||||
### Yama
|
||||
|
||||
Yama (`yama`) restricts the usage of `ptrace` (process-trace). Where `ptrace` is a system call that enables the tracing of a process or signalling to a process from within another process. Although by default (without yama) only limited communication is possible due to the small fixed-size block of memory that can be passed between the two processes. Yama attaches a `ptrace` permission level (0-3) to each process, with these levels defined as
|
||||
|
||||
| Level | Restriction |
|
||||
| :---: | ----------- |
|
||||
| 0 | No |
|
||||
| 1 | Descendants-only attach |
|
||||
| 2 | Admin-only attach |
|
||||
| 3 | No attach |
|
||||
|
||||
and therefore restricts which processes can trace or signal other processes, helping to mitigate certain types of attacks, such as privilege escalation.
|
||||
|
||||
### Integrity Policy Enforcement
|
||||
|
||||
Integrity Policy Enforcement (IPE) (`integrity`) takes a complementary approach to access control. Focusing on the immutable security properties inherent to system components. These properties are fundamental attributes or features of a system component that cannot be altered, ensuring a consistent and reliable basis for security decisions.
|
||||
|
||||
### SELinux
|
||||
|
||||
Security-Enhanced Linux implements mandatory access control (MAC) policies that restrict how processes interact with each other and with files.
|
||||
|
||||
### AppArmor
|
||||
|
||||
AppArmor is a security module that provides a simpler alternative to SELinux. It can dissallow access to files which the process would not require, as defined by the apparmor profile. Install the necessary packages: (1)
|
||||
{ .annotate }
|
||||
|
||||
1. For Gentoo Linux make sure to set the `apparmor` USE flag.
|
||||
|
||||
=== "Alpine Linux"
|
||||
|
||||
``` shell-session
|
||||
sh# apk add apparmor apparmor-utils apparmor-profiles
|
||||
```
|
||||
|
||||
=== "Gentoo Linux"
|
||||
|
||||
``` shell-session
|
||||
sh# emerge -a apparmor apparmor-utils apparmor-profiles
|
||||
```
|
||||
|
||||
and add it to the boot runlevel:
|
||||
|
||||
``` shell-session
|
||||
sh# rc-update add apparmor boot
|
||||
```
|
||||
|
||||
Add `apparmor` to the kernel `cmdline` to make it operational:
|
||||
|
||||
``` shell title="/etc/kernel/cmdline"
|
||||
... lsm=...,apparmor apparmor=1 ...
|
||||
```
|
||||
|
||||
Then reconfigure the `kernel`:
|
||||
|
||||
=== "Alpine Linux"
|
||||
|
||||
``` shell-session
|
||||
sh# apk fix kernel-hooks
|
||||
```
|
||||
|
||||
=== "Gentoo Linux"
|
||||
|
||||
``` shell-session
|
||||
sh# emerge --config gentoo-kernel
|
||||
```
|
||||
|
||||
You can check the status of `apparmor` with `apparmor-utils`:
|
||||
|
||||
``` shell-session
|
||||
sh# aa-status
|
||||
```
|
||||
|
||||
## Kernel boot parameters
|
||||
|
||||
Boot parameters configure the bootloader to parse the relevant settings to the kernel at boot. Hardening the boot process will improve the overall security of the system. The listed boot parameters in this chapter can be parsed into the kernel `cmdline`:
|
||||
|
||||
``` shell title="/etc/kernel/cmdline"
|
||||
... slab_nomerge init_on_alloc=1 init_on_free=1 page_alloc.shuffle=1 pti=on ...
|
||||
```
|
||||
|
||||
### Mitigations of system vulnerabilities
|
||||
|
||||
* The setting `slab_nomerge` disables [slab merging](https://en.wikipedia.org/wiki/Slab_allocation) which helps to protect against heap exploitation.
|
||||
|
||||
* The settings `init_on_alloc=1 init_on_free=1` enable zeroing of memory during allocation and free time, which helps to mitigate use-after-free vulnerabilities.
|
||||
|
||||
* The setting `page_alloc.shuffle=1` randomises page allocator freelists, making page allocations less predictable. (1)
|
||||
{ .annotate }
|
||||
|
||||
1. Setting this parameter actually improves performance.
|
||||
|
||||
* The setting `pti=on` enables [kernel page-table isolation]() that mitigates the [meltdown vulnerability](https://en.wikipedia.org/wiki/Meltdown_(security_vulnerability)) and helps to protect against attempts to bypass [kernel address space layout randomisation](https://en.wikipedia.org/wiki/Address_space_layout_randomization).
|
||||
|
||||
* The setting `randomize_kstack_offset=on` randomises the kernel stack offset on each syscall, which helps to protect against attacks that rely on deterministic kernel stack layouts.
|
||||
|
||||
* The setting `vsyscall=none` disables the deprecated `vsyscalls`.
|
||||
|
||||
* The setting `debugfs=off` disables the debugfs, removing a source of sensitive information about the kernel.
|
||||
|
||||
* The setting `module.sig_enforce=1` enforces that only signed kernel modules can be loaded.
|
||||
|
||||
* The setting `lockdown=confidentiality` sets the strictest option of the `lockdown` security module.
|
||||
|
||||
* The setting `mce=0` causes the kernel to panic on uncorrectable errors in ECC memory. This setting is unnecessary for non-ECC memory. (1)
|
||||
{ .annotate }
|
||||
|
||||
1. ECC memory from a security and a redundancy perspective is always recommended. The ZFS filesystem also functions better with ECC memory.
|
||||
|
||||
### Hardware specific mitigations of vulnerabilities
|
||||
|
||||
* The setting `spectre_v2=on` enables the mitigation of [spectre](https://en.wikipedia.org/wiki/Spectre_(security_vulnerability)), a speculative execution CPU vulnerability that is present in all pre-2019 CPUs.
|
||||
|
||||
* The setting `spec_store_bypass_disable=on` disables [Speculative Store Bypass](https://en.wikipedia.org/wiki/Speculative_Store_Bypass) (SSB), in all pre-2019 CPUs there is a vulnerability in the SSB.
|
||||
|
||||
* The setting `tsx=off` disables [Transactional Synchronisation Extensions](https://en.wikipedia.org/wiki/Transactional_Synchronization_Extensions) (TSX), which is a feature of pre-2019 Intel CPUs. TSXs are vulnerable to cache [side-channel attacks](https://en.wikipedia.org/wiki/Side-channel_attack).
|
||||
|
||||
* The setting `tsx_async_abort=full` mitigates the TSX vulnerability if you are stupid enough to keep TSX enabled.
|
||||
|
||||
* The setting `mds=full` enables the mitigation of the [Micro-architectural Data Sampling](https://en.wikipedia.org/wiki/Microarchitectural_Data_Sampling) (MDS), a set of weaknesses in pre-2020 Intel x86_64 CPUs.
|
||||
|
||||
* The setting `l1tf=flush` mitigates the [L1 Terminal Fault vulnerability](https://docs.kernel.org/admin-guide/hw-vuln/l1tf.html) present in pre-2019, by conditional flushing of the Level 1 Data Cache.
|
||||
|
||||
* The setting `kvm.nx_huge_pages=force` mitigates the [iTLB multihit vulnerability](https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/multihit.html) present in pre-2019 Intel CPUs.
|
||||
|
||||
> So if you have a pre-2019 Intel CPU, throw it out of the window right now! The performance hit is quite significant with all these mitigations.
|
||||
|
||||
### Hardening the boot process
|
||||
|
||||
* The settings `quiet loglevel=0` prevent information leaks during boot and must be used in combination with the `kernel.printk` sysctl setting.
|
||||
|
||||
* The settings `rd.shell=0 rd.emergency.reboot=reboot` impose that at critical failure in the boot process the system should be rebooted and that the shell cannot be accessed at all times during this process. Hardening the boot process.
|
||||
|
||||
## Kernel sysctl settings
|
||||
|
||||
Kernel self-protection can be configured by creating:
|
||||
|
||||
``` shell title="/etc/sysctl.d/kernel.conf" linenums="1"
|
||||
kernel.kptr_restrict=2 #(1)!
|
||||
kernel.dmesg_restrict=1 #(2)!
|
||||
kernel.printk=3 3 3 3 #(3)!
|
||||
kernel.unprivileged_bpf_disabled=1 #(4)!
|
||||
net.core.bpf_jit_harden=2 #(5)!
|
||||
dev.tty.ldisc_autoload=0 #(6)!
|
||||
kernel.kexec_load_disabled=1 #(7)!
|
||||
kernel.sysrq=0 #(8)!
|
||||
kernel.perf_event_paranoid=3 #(9)!
|
||||
```
|
||||
|
||||
1. Mitigate kernel pointer leaks.
|
||||
2. Restrict kernel log to `CAP_SYSLOG` capability.
|
||||
3. Restrict kernel log in console during boot.
|
||||
4. Restrict eBPF to `CAP_SYSLOG` capability.
|
||||
5. Restrict eBPF to `CAP_SYSLOG` capability.
|
||||
6. Restrict TTY line disciplines to `CAP_SYS_MODULE` capability.
|
||||
7. Disable kexec (system call to boot another kernel during runtime).
|
||||
8. Disable SysRq key (debugging functionality).
|
||||
9. Restrict performance events to `CAP_PERFORM` capability.
|
||||
|
||||
Network protection can be configured by creating:
|
||||
|
||||
``` shell title="/etc/sysctl.d/network.conf" linenums="1"
|
||||
net.ipv4.icmp_echo_ignore_all=1 #(1)!
|
||||
net.ipv4.tcp_syncookies=1 #(2)!
|
||||
net.ipv4.tcp_rfc1337=1 #(3)!
|
||||
net.ipv4.tcp_sack=0 #(4)!
|
||||
net.ipv4.tcp_dsack=0 #(5)!
|
||||
net.ipv4.tcp_fack=0 #(6)!
|
||||
net.ipv4.conf.all.rp_filter=1 #(7)!
|
||||
net.ipv4.conf.default.rp_filter=1 #(8)!
|
||||
net.ipv4.conf.all.accept_redirects=0 #(9)!
|
||||
net.ipv4.conf.default.accept_redirects=0 #(10)!
|
||||
net.ipv4.conf.all.secure_redirects=0 #(11)!
|
||||
net.ipv4.conf.default.secure_redirects=0 #(12)!
|
||||
net.ipv6.conf.all.accept_redirects=0 #(13)!
|
||||
net.ipv6.conf.default.accept_redirects=0 #(14)!
|
||||
net.ipv4.conf.all.send_redirects=0 #(15)!
|
||||
net.ipv4.conf.default.send_redirects=0 #(16)!
|
||||
net.ipv4.conf.all.accept_source_route=0 #(17)!
|
||||
net.ipv4.conf.default.accept_source_route=0 #(18)!
|
||||
net.ipv6.conf.all.accept_source_route=0 #(19)!
|
||||
net.ipv6.conf.default.accept_source_route=0 #(20)!
|
||||
```
|
||||
|
||||
1. Ignore all ICMP requests, to avoid [Smurf attacks](https://en.wikipedia.org/wiki/Smurf_attack).
|
||||
2. Restricts resources handling SYN requests, helps protect against [SYN flood attacks](https://en.wikipedia.org/wiki/SYN_flood).
|
||||
3. Drops RST packets for sockets in the time-wait state, to avoid [time-wait assassination attacks](https://datatracker.ietf.org/doc/html/rfc1337).
|
||||
4. Disables TCP SACK, for servers it could be relevant to keep this enabled.
|
||||
5. Disables TCP SACK, for servers it could be relevant to keep this enabled.
|
||||
6. Disables TCP SACK, for servers it could be relevant to keep this enabled.
|
||||
7. Enables source validation of packets received from all interfaces, to avoid [IP spoofing](https://en.wikipedia.org/wiki/IP_address_spoofing).
|
||||
8. Enables source validation of packets received from all interfaces, to avoid [IP spoofing](https://en.wikipedia.org/wiki/IP_address_spoofing).
|
||||
9. Disables ICMP redirect acceptance and sending to prevent [man-in-the-middle attacks](https://en.wikipedia.org/wiki/Man-in-the-middle_attack).
|
||||
10. Disables ICMP redirect acceptance and sending to prevent [man-in-the-middle attacks](https://en.wikipedia.org/wiki/Man-in-the-middle_attack).
|
||||
11. Disables ICMP redirect acceptance and sending to prevent [man-in-the-middle attacks](https://en.wikipedia.org/wiki/Man-in-the-middle_attack).
|
||||
12. Disables ICMP redirect acceptance and sending to prevent [man-in-the-middle attacks](https://en.wikipedia.org/wiki/Man-in-the-middle_attack).
|
||||
13. Disables ICMP redirect acceptance and sending to prevent [man-in-the-middle attacks](https://en.wikipedia.org/wiki/Man-in-the-middle_attack).
|
||||
14. Disables ICMP redirect acceptance and sending to prevent [man-in-the-middle attacks](https://en.wikipedia.org/wiki/Man-in-the-middle_attack).
|
||||
15. Disables ICMP redirect acceptance and sending to prevent [man-in-the-middle attacks](https://en.wikipedia.org/wiki/Man-in-the-middle_attack).
|
||||
16. Disables ICMP redirect acceptance and sending to prevent [man-in-the-middle attacks](https://en.wikipedia.org/wiki/Man-in-the-middle_attack).
|
||||
17. Disables source routing to prevent [man-in-the-middle attacks](https://en.wikipedia.org/wiki/Man-in-the-middle_attack).
|
||||
18. Disables source routing to prevent [man-in-the-middle attacks](https://en.wikipedia.org/wiki/Man-in-the-middle_attack).
|
||||
19. Disables source routing to prevent [man-in-the-middle attacks](https://en.wikipedia.org/wiki/Man-in-the-middle_attack).
|
||||
20. Disables source routing to prevent [man-in-the-middle attacks](https://en.wikipedia.org/wiki/Man-in-the-middle_attack).
|
||||
|
||||
Protection of the user space can be configured by creating:
|
||||
|
||||
``` shell title="/etc/sysctl.d/user.conf" linenums="1"
|
||||
kernel.yama.ptrace_scope=2 #(1)!
|
||||
vm.mmap_rnd_bits=32 #(2)!
|
||||
vm.mmap_rnd_compat_bits=16 #(3)!
|
||||
fs.protected_symlinks=1 #(4)!
|
||||
fs.protected_hardlinks=1 #(5)!
|
||||
fs.protected_fifos=2 #(6)!
|
||||
fs.protected_regular=2 #(7)!
|
||||
```
|
||||
|
||||
1. Restrict `ptrace` usage to level 2 (only processes with `CAP_SYS_PTRACE` capability).
|
||||
2. Increase the entropy for mmap ASLR, compatible with `x86_64`.
|
||||
3. Increase the entropy for mmap ASLR, compatible with `x86_64`.
|
||||
4. Restricts symlink following to only well-defined owner paths, preventing [TOC/TOU races](https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use).
|
||||
5. Restricts symlink following to only well-defined owner paths, preventing [TOC/TOU races](https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use).
|
||||
6. Prevent file creation in high-risk environments, helps to protect against [spoofing attakcs](https://en.wikipedia.org/wiki/Spoofing_attack).
|
||||
7. Prevent file creation in high-risk environments, helps to protect against [spoofing attakcs](https://en.wikipedia.org/wiki/Spoofing_attack).
|
||||
|
||||
## Hardened memory allocator
|
||||
|
||||
The default memory allocator of `musl` is already reasonably secure but not as secure as [hardened-malloc](https://github.com/GrapheneOS/hardened_malloc/), install it with:
|
||||
|
||||
=== "Alpine Linux"
|
||||
|
||||
``` shell-session
|
||||
sh# apk add hardened-malloc
|
||||
```
|
||||
|
||||
=== "Gentoo Linux"
|
||||
|
||||
``` shell-session
|
||||
sh# emerge -a hardened-malloc
|
||||
```
|
||||
|
||||
and set it to system-wide edit:
|
||||
|
||||
``` shell title="/etc/ld-musl-x86_64.path"
|
||||
/usr/lib/libhardened_malloc.so #(1)!
|
||||
/lib
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
```
|
||||
|
||||
1. If problems with graphical applications occur the light variant of hardened-malloc `/usr/lib/libhardened_malloc-light.so` may also be used instead of `/usr/lib/libhardened_malloc.so`.
|
||||
|
||||
To accomodate the large number of guard pages created by `hardened-malloc` impose that we should set the following:
|
||||
|
||||
``` shell title="/etc/sysctl.d/malloc.conf"
|
||||
vm.max_map_count=1048576
|
||||
```
|
||||
|
||||
## Entropy
|
||||
|
||||
Improve the security of the system by increasing the entropy with the `jitterentropy` kernel module, install it with:
|
||||
|
||||
=== "Alpine Linux"
|
||||
|
||||
``` shell-session
|
||||
sh# apk add jitterentropy-library
|
||||
```
|
||||
|
||||
=== "Gentoo Linux"
|
||||
|
||||
``` shell-session
|
||||
sh# emerge -a jitterentropy-library
|
||||
```
|
||||
|
||||
and make sure that the module gets loaded:
|
||||
|
||||
``` shell title="/etc/modules-load.d/entropy.conf"
|
||||
jitterentropy_rng
|
||||
```
|
||||
|
||||
## PAM
|
||||
|
||||
There are a few changes that can be made to improve login protection.
|
||||
|
||||
First install PAM through `util-linux-login`:
|
||||
|
||||
=== "Alpine Linux"
|
||||
|
||||
``` shell-session
|
||||
sh# apk add util-linux-login
|
||||
```
|
||||
|
||||
=== "Gentoo Linux"
|
||||
|
||||
``` shell-session
|
||||
sh# emerge -a util-linux-login
|
||||
```
|
||||
|
||||
Delays can be a deterent against bruteforcing login attempts. Simply add the following line:
|
||||
|
||||
``` shell title="/etc/pam.d/login"
|
||||
auth optional pam_faildelay.so delay=5000000
|
||||
```
|
||||
|
||||
which will add a 5 second delay between login attempts.
|
||||
|
||||
The system can also enforce a stronger hash algorithm for a more secure login protector by editing
|
||||
|
||||
``` shell title="/etc/pam.d/base-password"
|
||||
password required pam_unix.so nullock sha512 shadow rounds=1000000
|
||||
```
|
||||
|
||||
> If an account has already been created then change your password so that it is also secure, with: `passwd <username>`. When creating a password make sure that it is at least 8 characters long.
|
363
docs/server-os/posts/03-container-management-podman-runit.md
Normal file
363
docs/server-os/posts/03-container-management-podman-runit.md
Normal file
|
@ -0,0 +1,363 @@
|
|||
---
|
||||
title: Rootless container management with Podman and runit
|
||||
slug: rootless-container-management-with-podman-and-runit
|
||||
date: 2024-08-30
|
||||
draft: true
|
||||
authors:
|
||||
- luc
|
||||
tags:
|
||||
- Alpine Linux
|
||||
- Gentoo Linux
|
||||
categories:
|
||||
- Container management
|
||||
---
|
||||
|
||||
Containers and pods (a collection of containers in the same namespace) enables easy and secure management of hosted applications. Rootless containers and pods can be deployed on a server with [Podman](https://podman.io/) as the rootless container engine and [runit]() as the user service manager. The service manager will be set-up to automatically start and update the containers and pods at boot and to periodically back-up the volumes and databases of the pods.
|
||||
|
||||
<!-- more -->
|
||||
|
||||
## User services with runsvdir
|
||||
|
||||
Using `runsvdir` requires `runit` to be installed on the system:
|
||||
|
||||
=== "Alpine Linux"
|
||||
|
||||
``` shell-session
|
||||
sh# apk add runit
|
||||
```
|
||||
|
||||
=== "Gentoo Linux"
|
||||
|
||||
``` shell-session
|
||||
sh# emerge -a runit
|
||||
```
|
||||
|
||||
Now create an `openrc` entry that will manage `runsvdir`:
|
||||
|
||||
``` shell title="/etc/init.d/runsvdir-user"
|
||||
#!/sbin/openrc-run
|
||||
|
||||
user="${RC_SVCNAME##*.}"
|
||||
svdir="/home/${user}/.local/service"
|
||||
pidfile="/run/runsvdir-user.${user}.pid"
|
||||
|
||||
command="/usr/bin/runsvdir"
|
||||
command_args="$svdir"
|
||||
command_user="$user"
|
||||
command_background=true
|
||||
|
||||
depend()
|
||||
{
|
||||
after network-online
|
||||
}
|
||||
```
|
||||
|
||||
Make the entry executable, link user `<username>` and add the service to the default runlevel:
|
||||
|
||||
``` shell-session
|
||||
sh# chmod +x /etc/init.d/runsvdir-user
|
||||
sh# ln -s /etc/init.d/runsvdir-user /etc/init.d/runsvdir-user.<username>
|
||||
sh# rc-update add runsvdir-user.<username> default
|
||||
```
|
||||
|
||||
> This process can of course be repeated for any number of users.
|
||||
|
||||
## Container management with Podman
|
||||
|
||||
Install `podman` with:
|
||||
|
||||
=== "Alpine Linux"
|
||||
|
||||
``` shell-session
|
||||
sh# apk add podman
|
||||
```
|
||||
|
||||
=== "Gentoo Linux"
|
||||
|
||||
``` shell-session
|
||||
sh# emerge -a podman
|
||||
```
|
||||
|
||||
Rootless `podman` requires `cgroups` to run, therefore add it to the default runlevel:
|
||||
|
||||
``` shell-session
|
||||
sh# rc-update add cgroups default
|
||||
```
|
||||
|
||||
Set up the network namespace configuration for the user:
|
||||
|
||||
``` shell-session
|
||||
sh# modprobe tun
|
||||
sh# echo tun >> /etc/modules-load.d/tun.conf
|
||||
sh# for i in subuid subgid; do
|
||||
> echo <username>:100000:65536 >> /etc/$i
|
||||
> done
|
||||
```
|
||||
|
||||
Run the following container to verify if everything works:
|
||||
|
||||
``` shell-session
|
||||
sh$ podman run --rm hello-world
|
||||
```
|
||||
|
||||
### Management of containers
|
||||
|
||||
To run a single container create:
|
||||
|
||||
``` shell title="~/.config/sv/<container-name>/run"
|
||||
#!/bin/sh
|
||||
|
||||
command="/usr/bin/podman"
|
||||
command_args="run --replace --rm --name=<container-name> --network=pasta"
|
||||
env="<container-envs>"
|
||||
ports="<container-ports>"
|
||||
mounts="<container-mounts>"
|
||||
image="<container-image>"
|
||||
|
||||
exec 2>&1
|
||||
exec $command $command_args $env $ports $mounts $image
|
||||
```
|
||||
|
||||
Make it executable and link it to the service directory:
|
||||
|
||||
``` shell-session
|
||||
sh$ chmod +x ~/.config/sv/<container-name>/run
|
||||
sh$ ln -s <home>/.config/sv/<container-name> <home>/.local/service
|
||||
```
|
||||
|
||||
### Management of pods
|
||||
|
||||
To check if a pod is running, create:
|
||||
|
||||
``` shell title="~/.local/bin/checkpod"
|
||||
#!/bin/sh
|
||||
|
||||
. ./conf
|
||||
|
||||
exec 2>&1
|
||||
|
||||
state=0
|
||||
|
||||
while [ $state == 0 ]
|
||||
do
|
||||
sleep 10
|
||||
$command pod inspect ${name}-pod | grep -q '"State": "Running"' || state=1
|
||||
done
|
||||
```
|
||||
|
||||
and make it executable with:
|
||||
|
||||
``` shell-session
|
||||
sh$ chmod +x ~/.local/bin/checkpod
|
||||
```
|
||||
|
||||
To run a pod configured with `~/.config/pods/<pod-name>/<pod-name>.yml`, see [alpine-server](https://git.lucbijl.nl/luc/alpine-server) for examples, we setup the `runit` entry with a `conf`, `run` and `finish` structure. Therefore create:
|
||||
|
||||
``` shell title="~/.config/sv/{pod-name}/conf"
|
||||
name="<pod-name>"
|
||||
home="<home>"
|
||||
pod_location="${home}/.config/pods/<pod-name>"
|
||||
bin_location="${home}/.local/bin"
|
||||
command="/usr/bin/podman"
|
||||
command_args="--replace --network=pasta"
|
||||
```
|
||||
|
||||
will contain all the relevant configuration specific to the pod. Now create:
|
||||
|
||||
``` shell title="~/.config/sv/{pod-name}/run"
|
||||
#!/bin/sh
|
||||
|
||||
. ./conf
|
||||
|
||||
exec 2>&1
|
||||
$command kube play $command_args ${pod_location}/${name}-pod.yml
|
||||
exec ${bin_location}/checkpod
|
||||
```
|
||||
|
||||
and create:
|
||||
|
||||
``` shell title="~/.config/sv/{pod-name}/finish"
|
||||
#!/bin/sh
|
||||
|
||||
. ./conf
|
||||
|
||||
exec 2>&1
|
||||
exec $command kube down ${pod_location}/${name}-pod.yml
|
||||
```
|
||||
|
||||
will stay the same for any pod.
|
||||
|
||||
Make both `run` and `finish` executable:
|
||||
|
||||
``` shell-session
|
||||
sh$ chmod +x ~/.config/sv/<pod-name>/run
|
||||
sh$ chmod +x ~/.config/sv/<pod-name>/finish
|
||||
```
|
||||
|
||||
Finally, link the pod to the service directory:
|
||||
|
||||
``` shell-session
|
||||
sh$ ln -s <home>/.config/sv/<pod-name> <home>/.local/service
|
||||
```
|
||||
|
||||
### Backup of volumes and databases
|
||||
|
||||
To back up volumes of containers and postgresql databases create:
|
||||
|
||||
``` shell title="~/.local/bin/dump"
|
||||
#!/bin/sh
|
||||
|
||||
command="/usr/bin/podman"
|
||||
|
||||
# Dumps databases
|
||||
|
||||
postgres_databases="<list-of-postgres-databases>"
|
||||
|
||||
for database in $postgres_databases
|
||||
do
|
||||
exec $command exec -it ${database}-pod-postgres sh -c "pg_dumpall -U postgres | gzip > /dump/${database}.sql.gz"
|
||||
done
|
||||
|
||||
# Exports volumes
|
||||
|
||||
volumes="<list-of-volumes>"
|
||||
|
||||
for volume in $volumes
|
||||
do
|
||||
exec $command volume export $volume --output <home>/.volumes/${volume}.tar
|
||||
done
|
||||
```
|
||||
|
||||
Make it executable:
|
||||
|
||||
``` shell-session
|
||||
sh$ chmod +x ~/.local/bin/dump
|
||||
```
|
||||
|
||||
Automate it with `snooze`:
|
||||
|
||||
=== "Alpine Linux"
|
||||
|
||||
``` shell-session
|
||||
sh# apk add snooze
|
||||
```
|
||||
|
||||
=== "Gentoo Linux"
|
||||
|
||||
``` shell-session
|
||||
sh# emerge -a snooze
|
||||
```
|
||||
|
||||
and create the corresponding `runit` entry:
|
||||
|
||||
``` shell title="~/.config/sv/dump/run"
|
||||
#!/bin/sh
|
||||
|
||||
exec 2>&1
|
||||
exec snooze -H* /home/neutrino/.local/bin/dump
|
||||
```
|
||||
|
||||
which executes dump every hour.
|
||||
|
||||
Make it executable and link it to the service directory:
|
||||
|
||||
``` shell-session
|
||||
sh$ chmod +x ~/.config/sv/dump/run
|
||||
sh$ ln -s <home>/.config/dump <home>/.local/service
|
||||
```
|
||||
|
||||
Then `restic` can be used to back up the `.dump` and `.volumes` folders to another server if necessary.
|
||||
|
||||
By creating:
|
||||
|
||||
``` shell title="~/.local/bin/load"
|
||||
#!/bin/sh
|
||||
|
||||
command="/usr/bin/podman"
|
||||
|
||||
# Loads dumped databases
|
||||
|
||||
postgres_databases="<list-of-postgres-databases>"
|
||||
|
||||
for database in $postgres_databases
|
||||
do
|
||||
exec $command exec -it ${database}-pod-postgres sh -c "gunzip -c /dump/${database}.sql.gz | psql -U postgres"
|
||||
done
|
||||
|
||||
# Imports volumes
|
||||
|
||||
volumes="<list-of-volumes>"
|
||||
|
||||
for volume in $volumes
|
||||
do
|
||||
exec $command volume import $volume <home>/.volumes/${volume}.tar
|
||||
done
|
||||
```
|
||||
|
||||
the volumes and postgresql databases can be reloaded.
|
||||
|
||||
Do not forget to make it executable:
|
||||
|
||||
``` shell-session
|
||||
sh$ chmod +x ~/.local/bin/load
|
||||
```
|
||||
|
||||
## Proxying with Caddy
|
||||
|
||||
While it would be more optimal to run a reverse proxy in a container and link the network namespaces to this container, this is unfortunately not possible with `pasta` user network namespaces. Therefore, the reverse proxy should be run in front of the containers and thus on the system.
|
||||
|
||||
Caddy is a simple and modern web-server that supports automatic HTTPS and can act as a reverse-proxy. Install `caddy` and `libcap` (necessary dependency) with:
|
||||
|
||||
=== "Alpine Linux"
|
||||
|
||||
``` shell-session
|
||||
sh# apk add caddy libcap
|
||||
```
|
||||
|
||||
=== "Gentoo Linux"
|
||||
|
||||
``` shell-session
|
||||
sh# emerge -a caddy libcap
|
||||
```
|
||||
|
||||
Give `caddy` privileges to accesss all ports: (1)
|
||||
{ .annotate }
|
||||
|
||||
1. Such that we are able to run `caddy` rootless.
|
||||
|
||||
``` shell-session
|
||||
sh# setcap cap_net_bind_service=+ep /usr/sbin/caddy
|
||||
```
|
||||
|
||||
Create the `caddyfile` (1) according to your needs (2). Then convert it with the following to make it persistent:
|
||||
{ .annotate }
|
||||
|
||||
1. The configuration file of `caddy`.
|
||||
2. See [alpine-server](https://git.lucbijl.nl/luc/alpine-server) for examples.
|
||||
|
||||
``` shell-session
|
||||
sh$ caddy adapt -c ~/.config/caddy/caddyfile -p > ~/.config/caddy/caddy.json
|
||||
```
|
||||
|
||||
Create the corresponding `runit` entry for `caddy`:
|
||||
|
||||
``` shell title="~/.config/sv/caddy/run"
|
||||
#!/bin/sh
|
||||
|
||||
command="/usr/sbin/caddy"
|
||||
command_args="run"
|
||||
|
||||
exec ps | grep '[${command}] ${command_args}' > /dev/null
|
||||
|
||||
if [$? != 0]; then
|
||||
exec 2>&1
|
||||
exec $command $command_args
|
||||
fi
|
||||
```
|
||||
|
||||
Make it executable and link it to the service directory:
|
||||
|
||||
``` shell-session
|
||||
sh$ chmod +x ~/.config/sv/caddy/run
|
||||
sh$ ln -s <home>/.config/sv/caddy <home>/.local/service
|
||||
```
|
|
@ -20,6 +20,7 @@ theme:
|
|||
- search.suggest
|
||||
- search.highlight
|
||||
- search.share
|
||||
- content.tabs.link
|
||||
- content.code.copy
|
||||
- content.code.annotate
|
||||
# logo: assets/ampel-logo.png
|
||||
|
@ -46,6 +47,8 @@ markdown_extensions:
|
|||
- md_in_html
|
||||
- pymdownx.details
|
||||
- pymdownx.superfences
|
||||
- pymdownx.tabbed:
|
||||
alternate_style: true
|
||||
- pymdownx.highlight:
|
||||
anchor_linenums: true
|
||||
line_spans: __span
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue