-
Notifications
You must be signed in to change notification settings - Fork 376
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
62 additions
and
400 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,7 +2,7 @@ | |
SPDX-License-Identifier: MIT | ||
path: "/tutorials/how-to-install-archlinux-on-a-hetzner-cloud-server" | ||
slug: "how-to-install-archlinux-on-a-hetzner-cloud-server" | ||
date: "2022-05-25" | ||
date: "2024-09-20" | ||
title: "How to install Arch Linux on a Hetzner Cloud server" | ||
short_description: "In this tutorial we will learn how to install Arch Linux on any system running a live ISO" | ||
tags: ["Hetzner Cloud", "Arch Linux", "linux"] | ||
|
@@ -11,15 +11,15 @@ author_link: "https://github.com/Huanzo" | |
author_img: "https://avatars3.githubusercontent.com/u/28699007" | ||
author_description: "" | ||
language: "en" | ||
available_languages: ["en","ru"] | ||
available_languages: ["en"] | ||
header_img: "header-7" | ||
cta: "cloud" | ||
--- | ||
|
||
## Introduction | ||
|
||
In this article we will install a barebones Arch Linux system on a server that is currently running an OS from RAM or a live ISO. | ||
As long as the target disks are not in use any linux distribution will work. | ||
As long as the target disks are not in use, any linux distribution will work. | ||
For this tutorial I will be using a Hetzner Cloud server booted into the Rescue System. | ||
|
||
**Important information** | ||
|
@@ -37,7 +37,7 @@ I will also use the prompt text to indicate which chroot we are currently in. | |
|
||
We will start by getting the current bootstrap image from a trusted Arch Linux mirror. | ||
This will provide us with the necessary tools for an arch installation. | ||
While we are at it we will also get the corresponding signature and verify the image before continuing our installation. | ||
While we are at it, we will also get the corresponding signature and verify the image before continuing our installation. | ||
|
||
```shell | ||
root@rescue ~ # curl -LO 'https://geo.mirror.pkgbuild.com/iso/latest/archlinux-bootstrap-x86_64.tar.zst' | ||
|
@@ -55,20 +55,21 @@ root@rescue ~ # curl -LO 'https://archlinux.org/iso/latest/archlinux-bootstrap-x | |
|
||
```shell | ||
root@rescue ~ # gpg --keyserver keyserver.ubuntu.com --keyserver-options auto-key-retrieve --verify archlinux-bootstrap-x86_64.tar.zst.sig | ||
gpg: Signature made Tue 01 Mar 2022 04:54:14 PM CET | ||
gpg: using RSA key 4AA4767BBC9C4B1D18AE28B77F2D434B9741E8AC | ||
gpg: issuer "[email protected]" | ||
gpg: key 7F2D434B9741E8AC: public key "Pierre Schmitz <[email protected]>" imported | ||
gpg: Total number processed: 1 | ||
gpg: imported: 1 | ||
gpg: Signature made Sun 01 Sep 2024 02:43:27 PM CEST | ||
gpg: using EDDSA key 3E80CA1A8B89F69CBA57D98A76A5EF9054449A5C | ||
gpg: issuer "[email protected]" | ||
gpg: key 7F2D434B9741E8AC: public key "Pierre Schmitz <[email protected]>" imported | ||
gpg: key 76A5EF9054449A5C: public key "Pierre Schmitz <[email protected]>" imported | ||
gpg: Total number processed: 2 | ||
gpg: imported: 2 | ||
gpg: no ultimately trusted keys found | ||
gpg: Good signature from "Pierre Schmitz <pierre@archlinux.de>" [unknown] | ||
gpg: Good signature from "Pierre Schmitz <pierre@archlinux.org>" [unknown] | ||
gpg: WARNING: This key is not certified with a trusted signature! | ||
gpg: There is no indication that the signature belongs to the owner. | ||
Primary key fingerprint: 4AA4 767B BC9C 4B1D 18AE 28B7 7F2D 434B 9741 E8AC | ||
Primary key fingerprint: 3E80 CA1A 8B89 F69C BA57 D98A 76A5 EF90 5444 9A5C | ||
``` | ||
|
||
When no error occurs we can move on to unpacking the image. | ||
When no error occurs, we can move on to unpacking the image. | ||
|
||
```shell | ||
root@rescue ~ # tar xf archlinux-bootstrap-x86_64.tar.zst | ||
|
@@ -96,7 +97,8 @@ To do this we need to first configure a mirror and setup the pacman keyring and | |
|
||
```shell | ||
[root@bootstrap /]# echo 'Server = https://geo.mirror.pkgbuild.com/$repo/os/$arch' > /etc/pacman.d/mirrorlist | ||
|
||
``` | ||
```shell | ||
[root@bootstrap /]# pacman-key --init | ||
gpg: /etc/pacman.d/gnupg/trustdb.gpg: trustdb created | ||
gpg: no ultimately trusted keys found | ||
|
@@ -105,34 +107,36 @@ gpg: porting secret keys from '/etc/pacman.d/gnupg/secring.gpg' to gpg-agent | |
gpg: migration succeeded | ||
==> Generating pacman master key. This may take some time. | ||
gpg: Generating pacman keyring master key... | ||
gpg: key 207E15F05D559108 marked as ultimately trusted | ||
gpg: directory '/etc/pacman.d/gnupg/openpgp-revocs.d' created | ||
gpg: revocation certificate stored as '/etc/pacman.d/gnupg/opnpgp-revocs.d/0E95A7CBF1DC5CC8D05F1E4D207E15F05D559108.rev' | ||
gpg: revocation certificate stored as '/etc/pacman.d/gnupg/openpgp-revocs.d/AFB2F3A83C28CC51C20E0752282AC1A0C5C2A266.rev' | ||
gpg: Done | ||
==> Updating trust database... | ||
gpg: marginals needed: 3 completes needed: 1 trust model: pgp | ||
gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u | ||
|
||
``` | ||
```shell | ||
[root@bootstrap /]# pacman-key --populate archlinux | ||
==> Appending keys from archlinux.gpg... | ||
==> Locally signing trusted keys in keyring... | ||
-> Locally signed 6 keys. | ||
-> Locally signed 5 keys. | ||
==> Importing owner trust values... | ||
gpg: setting ownertrust to 4 | ||
gpg: setting ownertrust to 4 | ||
gpg: setting ownertrust to 4 | ||
gpg: inserting ownertrust of 4 | ||
gpg: setting ownertrust to 4 | ||
gpg: setting ownertrust to 4 | ||
==> Disabling revoked keys in keyring... | ||
-> Disabled 49 keys. | ||
-> Disabled 45 keys. | ||
==> Updating trust database... | ||
gpg: Note: third-party key signatures using the SHA1 algorithm are rejected | ||
gpg: (use option "--allow-weak-key-signatures" to override) | ||
gpg: marginals needed: 3 completes needed: 1 trust model: pgp | ||
gpg: depth: 0 valid: 1 signed: 6 trust: 0-, 0q, 0n, 0m, 0f, 1u | ||
gpg: depth: 1 valid: 6 signed: 94 trust: 0-, 0q, 0n, 6m, 0f, 0u | ||
gpg: depth: 2 valid: 88 signed: 32 trust: 88-, 0q, 0n, 0m, 0f, 0u | ||
gpg: next trustdb check due at 2022-05-06 | ||
|
||
gpg: depth: 0 valid: 1 signed: 5 trust: 0-, 0q, 0n, 0m, 0f, 1u | ||
gpg: depth: 1 valid: 5 signed: 101 trust: 0-, 0q, 0n, 5m, 0f, 0u | ||
gpg: depth: 2 valid: 77 signed: 22 trust: 77-, 0q, 0n, 0m, 0f, 0u | ||
gpg: next trustdb check due at 2024-11-09 | ||
``` | ||
```shell | ||
[root@bootstrap /]# pacman --noconfirm -Sy gdisk | ||
``` | ||
|
||
|
@@ -142,7 +146,7 @@ Our partitioning here is very simple. At minimum we need a boot partition (with | |
|
||
```shell | ||
[root@bootstrap /]# gdisk /dev/sda | ||
GPT fdisk (gdisk) version 1.0.8 | ||
GPT fdisk (gdisk) version 1.0.10 | ||
|
||
Partition table scan: | ||
MBR: protective | ||
|
@@ -159,15 +163,15 @@ Proceed? (Y/N): y | |
Command (? for help): n | ||
Partition number (1-128, default 1): | ||
First sector (34-40001502, default = 2048) or {+-}size{KMGTP}: | ||
Last sector (2048-40001502, default = 40001502) or {+-}size{KMGTP}: +1M | ||
Last sector (2048-40001502, default = 39999487) or {+-}size{KMGTP}: +1M | ||
Current type is 8300 (Linux filesystem) | ||
Hex code or GUID (L to show codes, Enter = 8300): ef02 | ||
Changed type of partition to 'BIOS boot partition' | ||
|
||
Command (? for help): n | ||
Partition number (2-128, default 2): | ||
First sector (34-40001502, default = 4096) or {+-}size{KMGTP}: | ||
Last sector (4096-40001502, default = 40001502) or {+-}size{KMGTP}: | ||
Last sector (4096-40001502, default = 39999487) or {+-}size{KMGTP}: | ||
Current type is 8300 (Linux filesystem) | ||
Hex code or GUID (L to show codes, Enter = 8300): | ||
Changed type of partition to 'Linux filesystem' | ||
|
@@ -186,15 +190,15 @@ We then format our root partition with the ext4 filesystem: | |
|
||
```shell | ||
[root@bootstrap /]# mkfs.ext4 /dev/sda2 | ||
mke2fs 1.46.5 (30-Dec-2021) | ||
mke2fs 1.47.1 (20-May-2024) | ||
/dev/sda2 contains a vfat file system | ||
Proceed anyway? (y,N) y | ||
Discarding device blocks: done | ||
Creating filesystem with 4999675 4k blocks and 1250928 inodes | ||
Filesystem UUID: 599505e1-d1bc-48be-a7e0-2aeb13a91612 | ||
Creating filesystem with 4999424 4k blocks and 1250928 inodes | ||
Filesystem UUID: c14d23b8-5754-49bc-bc27-d1cb48bd76e3 | ||
Superblock backups stored on blocks: | ||
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208, | ||
4096000 | ||
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208, | ||
4096000 | ||
|
||
Allocating group tables: done | ||
Writing inode tables: done | ||
|
@@ -209,18 +213,20 @@ We then mount it to `/mnt` and generate our fstab from that: | |
[root@bootstrap /]# genfstab -U /mnt >> /etc/fstab | ||
``` | ||
|
||
Now we can install Arch Linux via pacstrap. We will use this opportunity to install openssh as we will need it to connect to our server later. | ||
Now we can install Arch Linux via pacstrap. We will use this opportunity to install OpenSSH, as we will need it to connect to our server later. | ||
This may take some time depending on the speed of your internet connection and disks. | ||
|
||
```shell | ||
[root@bootstrap /]# pacstrap -G -M /mnt base grub linux linux-firmware openssh | ||
==> Creating install root at /mnt | ||
==> Installing packages to /mnt | ||
:: Synchronizing package databases... | ||
core 156.0 KiB 3.46 MiB/s 00:00 [############################################################] 100% | ||
extra 1715.8 KiB 105 MiB/s 00:00 [############################################################] 100% | ||
community 6.5 MiB 90.8 MiB/s 00:00 [############################################################] 100% | ||
resolving dependencies... | ||
core 117.2 KiB 514 KiB/s 00:00 [########################################] 100% extra 7.4 MiB 37.0 MiB/s 00:00 [########################################] 100%resolving dependencies... | ||
:: There are 2 providers available for libxtables.so=12-64: | ||
:: Repository core | ||
1) iptables 2) iptables-nft | ||
|
||
Enter a number (default=1): | ||
:: There are 3 providers available for initramfs: | ||
:: Repository core | ||
1) mkinitcpio | ||
|
@@ -232,12 +238,12 @@ looking for conflicting packages... | |
|
||
[...] | ||
|
||
Total Download Size: 428.47 MiB | ||
Total Installed Size: 852.18 MiB | ||
Total Download Size: 520.45 MiB | ||
Total Installed Size: 992.49 MiB | ||
|
||
[...] | ||
|
||
(12/12) Reloading system bus configuration... | ||
(13/13) Reloading system bus configuration... | ||
Skipped: Running in chroot. | ||
``` | ||
|
@@ -246,6 +252,7 @@ Total Installed Size: 852.18 MiB | |
We can now `exit` out of the bootstrap environment and change root into the installed system to finish setting up: | ||
```shell | ||
[root@bootstrap /]# exit | ||
root@rescue ~ # ./root.x86_64/usr/bin/arch-chroot root.x86_64/mnt | ||
``` | ||
|
@@ -263,6 +270,8 @@ Now it's time to install the bootloaded to our drive | |
[root@chroot /]# grub-install /dev/sda | ||
Installing for i386-pc platform. | ||
Installation finished. No error reported. | ||
``` | ||
```shell | ||
[root@chroot /]# grub-mkconfig -o /boot/grub/grub.cfg | ||
Generating grub configuration file ... | ||
Found linux image: /boot/vmlinuz-linux | ||
|
@@ -271,17 +280,20 @@ Found fallback initrd image(s) in /boot: initramfs-linux-fallback.img | |
Warning: os-prober will not be executed to detect other bootable partitions. | ||
Systems on them will not be added to the GRUB boot configuration. | ||
Check GRUB_DISABLE_OS_PROBER documentation entry. | ||
Adding boot menu entry for UEFI Firmware Settings ... | ||
done | ||
``` | ||
Networking will be managed by systemd-networkd. To enable we need to create the file `/etc/systemd/network/ether.network` with the following content: | ||
```file | ||
cat << EOF > /etc/systemd/network/ether.network | ||
[Match] | ||
Type=ether | ||
[Network] | ||
DHCP=yes | ||
EOF | ||
``` | ||
This will configure all ethernet network interfaces for DHCP. | ||
|
@@ -290,15 +302,15 @@ Now we activate the required services: | |
```shell | ||
[root@chroot /]# systemctl enable systemd-networkd | ||
Created symlink /etc/systemd/system/dbus-org.freedesktop.network1.service → /usr/lib/systemd/system/systemd-networkd.service. | ||
Created symlink /etc/systemd/system/multi-user.target.wants/systemd-networkd.service → /usr/lib/systemd/system/systemd-networkd.service. | ||
Created symlink /etc/systemd/system/sockets.target.wants/systemd-networkd.socket → /usr/lib/systemd/system/systemd-networkd.socket. | ||
Created symlink /etc/systemd/system/sysinit.target.wants/systemd-network-generator.service → /usr/lib/systemd/system/systemd-network-generator.service. | ||
Created symlink /etc/systemd/system/network-online.target.wants/systemd-networkd-wait-online.service → /usr/lib/systemd/system/systemd-networkd-wait-online.service. | ||
Created symlink '/etc/systemd/system/dbus-org.freedesktop.network1.service' → '/usr/lib/systemd/system/systemd-networkd.service'. | ||
Created symlink '/etc/systemd/system/multi-user.target.wants/systemd-networkd.service' → '/usr/lib/systemd/system/systemd-networkd.service'. | ||
Created symlink '/etc/systemd/system/sockets.target.wants/systemd-networkd.socket' → '/usr/lib/systemd/system/systemd-networkd.socket'. | ||
Created symlink '/etc/systemd/system/sysinit.target.wants/systemd-network-generator.service' → '/usr/lib/systemd/system/systemd-network-generator.service'. | ||
Created symlink '/etc/systemd/system/network-online.target.wants/systemd-networkd-wait-online.service' → '/usr/lib/systemd/system/systemd-networkd-wait-online.service'. | ||
[root@chroot /]# systemctl enable systemd-resolved | ||
Created symlink /etc/systemd/system/dbus-org.freedesktop.resolve1.service → /usr/lib/systemd/system/systemd-resolved.service. | ||
Created symlink /etc/systemd/system/multi-user.target.wants/systemd-resolved.service → /usr/lib/systemd/system/systemd-resolved.service. | ||
Created symlink '/etc/systemd/system/dbus-org.freedesktop.resolve1.service' → '/usr/lib/systemd/system/systemd-resolved.service'. | ||
Created symlink '/etc/systemd/system/sysinit.target.wants/systemd-resolved.service' → '/usr/lib/systemd/system/systemd-resolved.service'. | ||
``` | ||
Lastly we would like to have access via SSH to our system. | ||
|
@@ -308,15 +320,15 @@ For this simply create an authorized keys file at `/root/.ssh/authorized_keys` a | |
[root@chroot /]# mkdir /root/.ssh | ||
[root@chroot /]# echo "<your-ssh-pub-key>" >> /root/.ssh/authorized_keys | ||
[root@chroot /]# systemctl enable sshd | ||
Created symlink /etc/systemd/system/multi-user.target.wants/sshd.service → /usr/lib/systemd/system/sshd.service. | ||
Created symlink '/etc/systemd/system/multi-user.target.wants/sshd.service' → '/usr/lib/systemd/system/sshd.service'. | ||
``` | ||
We can now exit out from the chroot and reboot our system. | ||
After a few seconds you server should boot into your freshly installed Arch Linux and be reachable via SSH on port 22 using your public key. | ||
## Conclusion | ||
Congratulations! You now have a minimal Arch Linux installation on your server. From here on you can start installing additional services like docker, nginx, K8S, etc. | ||
Congratulations! You now have a minimal Arch Linux installation on your server. From here on you can start installing additional services like Docker, nginx, K8S, etc. | ||
##### License: MIT | ||
|
Oops, something went wrong.