Arch Post-Installation Checklist: Difference between revisions

From The Brainwrecked Wiki
Jump to navigation Jump to search
m Let's Encrypt: Added Automatic Renewal
m Yay: Fixed some code blocks
 
(137 intermediate revisions by the same user not shown)
Line 1: Line 1:
= Passwords & User Creation =
= Passwords & User Creation =


Make sure <code>root</code> has a password.
Make sure {{ic|root}} has a password.


Make sure you have a primary user set up.
Make sure you have a primary user set up.


# useradd -m -u <id -ge 1000> -g users -G wheel,games,video,audio,optical,storage,scanner,power <user>
{{bc|
# passwd <user>
sudo useradd -m -u <id -ge 1000> -g users -G wheel,games,video,audio,optical,storage,scanner,power <user>
sudo passwd <user>
}}


= /etc/fstab =
= /etc/fstab =
Line 12: Line 14:
= Time Zone =
= Time Zone =


# ln -sf /usr/share/zoneinfo/<region>/<city> /etc/localtime
{{bc|
# hwclock --systohc
sudo ln -sf /usr/share/zoneinfo/<region>/<city> /etc/localtime
sudo hwclock --systohc
}}


= Localization =
= Localization =


Un-comment your desired locales in <code>/etc/locale.conf</code>, then run
Un-comment your desired locales in {{ic|/etc/locale.conf}}, then run


# locale-gen
{{bc|sudo locale-gen}}


If you don't have the default <code>/etc/locale.gen</code> file:
If you don't have the default {{ic|/etc/locale.gen}} file:


# rm /etc/locale.gen
{{bc|
# pacman -Syu glibc
sudo rm /etc/locale.gen
sudo pacman -Syu glibc
}}


Edit <code>/etc/locale.conf</code> as you see fit
Edit {{ic|/etc/locale.conf}} as you see fit


LANG=en_US.UTF-8
{{hc|/etc/locale.conf|2=
LANGUAGE=en_US
<nowiki>LANG=en_US.UTF-8
LC_COLLATE=POSIX
LANGUAGE=en_US
LC_MESSAGES=C
LC_COLLATE=POSIX
LC_CTYPE=en_US.UTF-8
LC_MESSAGES=C
LC_NUMERIC=en_US.UTF-8
LC_CTYPE=en_US.UTF-8
LC_TIME=en_US.UTF-8
LC_NUMERIC=en_US.UTF-8
LC_MONETARY=en_US.UTF-8
LC_TIME=en_US.UTF-8
LC_PAPER=en_US.UTF-8
LC_MONETARY=en_US.UTF-8
LC_NAME=en_US.UTF-8
LC_PAPER=en_US.UTF-8
LC_ADDRESS=en_US.UTF-8
LC_NAME=en_US.UTF-8
LC_TELEPHONE=en_US.UTF-8
LC_ADDRESS=en_US.UTF-8
LC_MEASUREMENT=en_US.UTF-8
LC_TELEPHONE=en_US.UTF-8
LC_IDENTIFICATION=en_US.UTF-8
LC_MEASUREMENT=en_US.UTF-8
LC_IDENTIFICATION=en_US.UTF-8</nowiki>
}}


Set up <code>/etc/vconsole.conf</code> with a keymap and (optionally) a font:
Set up {{ic|/etc/vconsole.conf}} with a keymap and (optionally) a font:


KEYMAP=us
{{hc|/etc/vconsole.conf|2=
FONT=Lat2-Terminus16
KEYMAP=us
FONT=Lat2-Terminus16
}}


= Initramfs =
= Initramfs =
Line 52: Line 62:
Look for and edit the following lines:
Look for and edit the following lines:


MODULES=([amdgpu|bochs_drm|cirrus|i915|nouveau|(nvidia nvidia_modeset nvidia_uvm nvidia_drm)] [ehci_pci usb_storage]>)
{{hc|/etc/mkinitcpio.conf|2=
HOOKS=(base udev autodetect modconf block [zfs] filesystems keyboard fsck [encrypt] keymap consolefont)
<nowiki>MODULES=([amdgpu|bochs_drm|cirrus|i915|nouveau|(nvidia nvidia_modeset nvidia_uvm nvidia_drm)] [ehci_pci usb_storage]>)
COMPRESSION=lz4
HOOKS=(base udev autodetect modconf block [zfs] filesystems keyboard fsck [encrypt] keymap consolefont)
COMPRESSION=lz4</nowiki>
}}


= Networking =
= Networking =
Line 60: Line 72:
== Host Name ==
== Host Name ==


Make sure a host name is set in <code>/etc/hostname</code>
Make sure a host name is set in {{ic|/etc/hostname}}


Then edit <code>/etc/hosts</code>
Then edit {{ic|/etc/hosts}}


127.0.0.1 localhost.localdomain locahost
{{hc|/etc/hosts|2=
::1 localhost.localdomain localhost
127.0.0.1 localhost.localdomain locahost
127.0.1.1 <hostname>.localdomain <hostname>
::1 localhost.localdomain localhost
127.0.1.1 <hostname>.localdomain <hostname>
}}


== Static Addressing ==
== Static Addressing ==


Use <code>systemd-networkd</code> when a machine will use a static address without consulting a DHCP server.
Use {{ic|systemd-networkd}} when a machine will use a static address without consulting a DHCP server.


=== IPv4 Only ===
=== IPv4 Only ===


[Match]
{{hc|/etc/systemd/network/network.network|2=
MACAddress=<mac-address>
[Match]
[Network]
MACAddress=<mac-address>
Address=<ipv4-address>/<mask>
[Network]
DNS=<ipv4-address>
Address=<ipv4-address>/<mask>
Gateway=<ipv4-address>
DNS=<ipv4-address>
LinkLocalAddressing=no
Gateway=<ipv4-address>
IPv6AcceptRA=no
LinkLocalAddressing=no
IPv6AcceptRA=no
}}


=== IPv4 & IPv6 ===
=== IPv4 & IPv6 ===


[Match]
{{hc|/etc/systemd/network/network.network|2=
MACAddress=<mac-address>
[Match]
[Network]
MACAddress=<mac-address>
Address=<ipv6-address>/<mask>
[Network]
DNS=<ipv6-address>
Address=<ipv6-address>/<mask>
Gateway=<ipv6-address>
DNS=<ipv6-address>
Address=<ipv4-address>/<mask>
Gateway=<ipv6-address>
DNS=<ipv4-address>
Address=<ipv4-address>/<mask>
Gateway=<ipv4-address>
DNS=<ipv4-address>
Gateway=<ipv4-address>
}}


=== Dynamic Addressing ===
=== Dynamic Addressing ===


It's preferable to use <code>connman</code> or <code>Network Manager</code> for dynamic addresses as <code>systemd-networkd</code> doesn't play well with interfaces coming and going.
It's preferable to use {{ic|connman}} or {{ic|Network Manager}} for dynamic addresses as {{ic|systemd-networkd}} doesn't play well with interfaces coming and going.


If you'd rather use <code>systemd-networkd</code> for DHCP:
If you'd rather use {{ic|systemd-networkd}} for DHCP:


[Match]
{{hc|/etc/systemd/network/network.network|2=
MACAddress=<mac-address>
[Match]
[Network]
MACAddress=<mac-address>
DHCP=yes
[Network]
[DHCP]
DHCP=yes
UseMTU=true
[DHCP]
 
UseMTU=true
== IPTables Firewall ==
}}


# SIMPLE STATEFUL FIREWALL
= Packages =
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [100308:88697975]
:TCP - [0:0]
:UDP - [0:0]
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 8 -m conntrack --ctstate NEW -j ACCEPT
-A INPUT -m conntrack --ctstate INVALID -j DROP
-A INPUT -p udp -m conntrack --ctstate NEW -j UDP
-A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -m conntrack --ctstate NEW -j TCP
-A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
-A INPUT -p tcp -j REJECT --reject-with tcp-reset
-A INPUT -j REJECT --reject-with icmp-proto-unreachable
# OPEN NECESSARY PORTS HERE
-A TCP -p tcp -m tcp --dport 22 -j ACCEPT -m comment --comment "ssh"
-A TCP -p tcp -m tcp --dport 80 -j ACCEPT -m comment --comment "http"
-A TCP -p tcp -m tcp --dport 443 -j ACCEPT -m comment --comment "https"
-A TCP -p tcp -m tcp --dport 465 -j ACCEPT -m comment --comment "smtp secure"
-A TCP -p tcp -m tcp --dport 873 -j ACCEPT  -m comment --comment "rsync"
-A TCP -p tcp -m tcp --dport 993 -j ACCEPT -m comment --comment "imap secure"
-A TCP -p tcp -m tcp --dport 3000 -j ACCEPT -m comment --comment "cryptpad http"
-A TCP -p tcp -m tcp --dport 3001 -j ACCEPT -m comment --comment "cryptpad safe http"
-A TCP -p tcp -m tcp --dport 64738 -j ACCEPT -m comment --comment "mumble tcp"
-A UDP -p udp -m udp --dport 64738 -j ACCEPT -m comment --comment "mumble udp"
COMMIT
 
= Pacman =


== Mirror List ==
== Mirror List ==


Install and use <code>reflector</code> to automate the use and selection of mirrors.
Install and use {{ic|reflector}} to automate the use and selection of mirrors.


# pacman -Syu reflector
{{bc|
# reflector -c <country> -p https -l 5 --sort rate --save /etc/pacman.d/mirrorlist
sudo pacman -Syu reflector
sudo reflector -c <country> -p https -l 5 --sort rate --save /etc/pacman.d/mirrorlist
}}


== General Utilities ==
== Yay ==


# pacman -Syu --needed git rsync openssh
Make sure you have the {{ic|base-devel}} group installed.


== E-mail ==
{{bc|sudo pacman -Syu --needed base-devel git}}


# pacman -Syu --needed dovecot postfix rspamd swaks
Create a directory where AUR build files will go


== Nginx Web Server and Reverse Proxy ==
{{bc|1=
sudo mkdir /var/lib/pacman/aur
sudo chmod 1777 /var/lib/pacman/aur
mkdir /var/lib/pacman/aur/$(whoami)
}}


# pacman -Syu --needed ca-certificates certbot-nginx mariadb nginx php-fpm
Build {{ic|yay}}.


== Roundcube Web Mail ==
{{bc|1=<nowiki>
cd /var/lib/pacman/aur/$(whoami)
git clone https://aur.archlinux.org/yay.git
cd yay
makepkg -Ccisr
</nowiki>}}


# pacman -Syu --needed pigeonhole roundcube
The create the configuration file.


= SSH Setup =
{{hc|~/.config/yay/config.json|2=
{
"aururl": "https://aur.archlinux.org",
"buildDir": "/var/lib/pacman/aur/$USER",
"editor": "nano",
"editorflags": "",
"makepkgbin": "makepkg",
"makepkgconf": "",
"pacmanbin": "pacman",
"pacmanconf": "/etc/pacman.conf",
"tarbin": "bsdtar",
"redownload": "no",
"rebuild": "no",
"answerclean": "none",
"answerdiff": "all",
"answeredit": "",
"answerupgrade": "0",
"gitbin": "git",
"gpgbin": "gpg",
"gpgflags": "",
"mflags": "",
"sortby": "votes",
"gitflags": "",
"removemake": "yes",
"requestsplitn": 150,
"sortmode": 0,
"completionrefreshtime": 7,
"sudoloop": false,
"timeupdate": false,
"devel": true,
"cleanAfter": false,
"gitclone": true,
"provides": true,
"pgpfetch": true,
"upgrademenu": true,
"cleanmenu": true,
"diffmenu": true,
"editmenu": true,
"combinedupgrade": false,
"useask": false
}
}}


Look for and edit the following lines in <code>/etc/ssh/sshd_config</code>:
== General Utilities ==
 
Port <port>
AddressFamily <any|inet|inet6>
ListenAddress <ip4-address>
ListenAddress <ip6-address>
LogLevel VERBOSE
PermitRootLogin prohibit-password
PubkeyAuthentication yes
PasswordAuthentication no
PermitEmptyPasswords no
ChallengeResponseAuthentication no
UsePAM yes
AllowUsers <space-separated-list-of-users>
AllowAgentForwarding no
AllowTcpForwarding no
 
Then make sure the <code>sshd</code> service is enabled and running:
 
# systemctl enable --now sshd
 
= PHP-FPM =
 
Look for and edit the following lines in <code>/etc/php/php.ini</code>:
 
[PHP]
open_basedir = /srv/http/:/home/:/tmp/:/usr/share/pear/:/usr/share/webapps/:/dev/urandom:/proc/meminfo
include_path = ".:/php/includes:/usr/share/pear"
upload_max_filesize = 8M
extension=apcu
extension=dba
extension=exif
extension=gd
extension=gettext
extension=iconv
extension=intl
extension=sodium
extension=ldap
extension=mysqli
zend_extension=opcache
extension=pdo_mysql
extension=soap
[Pdo_mysql]
pdo_mysql.cache_size = 2000
[Session]
session.save_path = "/tmp/php/sessions"
[opcache]
opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=10000
opcache.revalidate_freq=1
opcache.save_comments=1
 
Then make sure the <code>php-fpm</code> service is enabled and running:
 
# systemctl enable --now php-fpm
 
= Nginx =
 
First, edit <code>/etc/nginx/nginx.conf</code>:
 
user http;
worker_processes 1; # one(1) worker or equal the number of _real_ cpu cores. 4=4 core cpu
worker_priority 15; # renice workers to reduce priority compared to system processes for machine health. Worst case nginx will get ~25% system resources at nice=15
worker_rlimit_nofile 1024; # maximum number of open files
worker_cpu_affinity auto;
events {
multi_accept on;
accept_mutex on; # serially accept() connections and pass to workers, efficient if workers gt 1
accept_mutex_delay 500ms; # worker process will accept mutex after this delay if not assigned. (default 500ms)
worker_connections 1024; # number of parallel or concurrent connections per worker_processes
}
http {
charset utf-8;
aio on; # asynchronous file I/O, fast with ZFS, make sure sendfile=off
sendfile off; # on for decent direct disk IO, off for VMs
tcp_nopush off; # turning on requires sendfile=on
tcp_nodelay on; # Nagle buffering algorithm, used for keepalive only
server_tokens off; # version number in error pages
log_not_found off;
types_hash_max_size 4096;
# MIME
include mime.types;
default_type application/octet-stream;
# logging
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log warn;
# SSL
ssl_session_timeout            1440m;
ssl_session_cache shared:le_nginx_SSL:10m;
ssl_session_tickets off;
ssl_prefer_server_ciphers off;
# Diffie-Hellman parameter for DHE ciphersuites
ssl_dhparam                    /etc/letsencrypt/ssl-dhparams.pem;
# Mozilla Intermediate configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 1.1.1.1 1.0.0.1 8.8.8.8 8.8.4.4 208.67.222.222 208.67.220.220 valid=60s;
resolver_timeout 2s;
# Size Limits
#client_body_buffer_size 8k;
#client_header_buffer_size 1k;
client_max_body_size 16M;
#large_client_header_buffers 4 4k/8k;
## From StackOverflow: for "upstream sent too big header while reading response header from upstream"
fastcgi_buffers 8 16k;
fastcgi_buffer_size 32k;
# Timeouts, do not keep connections open longer then necessary to reduce
# resource usage and deny Slowloris type attacks.
client_body_timeout 5s; # maximum time between packets the client can pause when sending nginx any data
client_header_timeout 5s; # maximum time the client has to send the entire header to nginx
keepalive_timeout 75s; # timeout which a single keep-alive client connection will stay open
send_timeout 15s; # maximum time between packets nginx is allowed to pause when sending the client data
## General Options
gzip off; # disable on the fly gzip compression due to higher latency, only use gzip_static
#gzip_http_version 1.0; # serve gzipped content to all clients including HTTP/1.0
gzip_static on; # precompress content (gzip -9) with an external script
#gzip_vary on; # send response header "Vary: Accept-Encoding"
gzip_proxied any; # allows compressed responses for any request even from proxies
ignore_invalid_headers on;
keepalive_requests 50; # number of requests per connection, does not affect SPDY
keepalive_disable none; # allow all browsers to use keepalive connections
max_ranges 1; # allow a single range header for resumed downloads and to stop large range header DoS attacks
msie_padding off;
open_file_cache max=1000 inactive=2h;
open_file_cache_errors on;
open_file_cache_min_uses 1;
open_file_cache_valid 1h;
output_buffers 1 512;
postpone_output 1440; # postpone sends to match our machine's MSS
read_ahead 512K; # kernel read head set to the output_buffers
recursive_error_pages on;
reset_timedout_connection on; # reset timed out connections freeing ram
server_name_in_redirect off; # if off, nginx will use the requested Host header
source_charset utf-8; # same value as "charset"
## Request limits
limit_req_zone $binary_remote_addr zone=gulag:1m rate=60r/m;
## Log Format
log_format main '$remote_addr $host $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $ssl_cipher $request_time';
# load configs
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*.conf;
}
 
Make the <code>sites-available</code> and <code>sites-enabled</code> directories.
 
# mkdir /etc/nginx/sites-{available,enabled}
 
Then make a site available by creating <code>/etc/nginx/sites-available/<domain>.conf</code>:<br/>
(Remove the <code>#</code> after setting up Let's Encrypt.)
 
<pre>server {
listen 80;
listen [::]:80;
server_name <domain>;
root /srv/http/$host;
index index.html index.php;
 
# if ($host = <domain>) {
# return 301 https://$host$request_uri;
# }
#
# return 404;
#
#}
#
#server {
#
# listen 443 ssl http2;
# listen [::]:443 ssl http2;
# server_name <domain>;
# root /srv/http/$host;
# index index.html index.php;
#
# ssl_certificate /etc/letsencrypt/live/<domain>/fullchain.pem;
# ssl_certificate_key /etc/letsencrypt/live/<domain>/privkey.pem;
# ssl_trusted_certificate /etc/letsencrypt/live/<domain>/chain.pem;
#
# fastcgi_param HTTPS on;
#
# add_header Strict-Transport-Security max-age=15768000;
add_header Cache-Control "public";
add_header X-Frame-Options "DENY";
 
access_log /var/log/nginx/access.log main buffer=32k;
error_log /var/log/nginx/error.log error;
limit_req zone=gulag burst=200 nodelay;
 
 
# ACME challenge
location ^~ /.well-known {
allow all;
alias /var/lib/letsencrypt/$host/.well-known;
default_type "text/plain";
try_files $uri =404;
}
 
location ~ /(data|conf|bin|inc)/ {
deny all;
}
 
# static file 404's are strict access by hostname aren't logged and expires header is set to maximum age
location ~* \.(jpg|jpeg|gif|css|png|js|ico|html)$ {
access_log off;
expires max;
}
 
location ~ \.php$ {
try_files $uri = 404;
fastcgi_pass unix:/run/php-fpm/php-fpm.sock;
fastcgi_index index.php;
include fastcgi.conf;
}
 
location ~ \.php5$ {
try_files $uri = 404;
fastcgi_pass unix:/run/php-fpm/php-fpm.sock;
fastcgi_index index.php5;
include fastcgi.conf;
}
 
location ~ /\.ht {
deny all;
}
 
}</pre>
 
Enable the site
 
# ln -s ../sites-available/<domain>.conf /etc/nginx/sites-enabled/<domain>.conf
 
Then create <code>index.php</code> for your new site.
 
<pre><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title>Server Configuration Confirmation</title>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
 
<body style="font-family:sans-serif;">
 
<h1>Web server is properly configured!</h1>
 
<?php echo "<h2>PHP is properly configured as well!</h2>" ?>
 
<p>Time to add some content!</p>
 
</body>
</html></pre>
 
Finally, make sure the <code>nginx</code> service is enabled and running:


# systemctl enable --now nginx
These packages supplement the base system.


= Let's Encrypt =
{{bc|yay -Syu --needed adduser archey3 arj bind-tools bzip2 dmidecode dnsutils fail2ban git haveged htop hwdetect inxi iotop lshw lzop nano ncdu openssh p7zip pacman-contrib perl-rename pkgfile polkit ranger rsync strace sudo tmux unrar unzip vim whois zip}}


{{bc|# certbot --nginx}}
If you are not running inside a VM, you may also wish to add these packages:


The {{ic|nginx}} plugin will guide you and help automate the process.
{{bc|yay -Syu hddtemp lm_sensors memtest86+ smartmontools}}


Take note that the {{ic|nginx}} configuration in this guide takes into account the settings suggested by {{ic|certbot}}.
The {{ic|havaged}} service can be enabled and started right away as no configuration is needed.


== Automatic Renewal ==
{{bc|sudo systemctl enable --now haveged}}


These will automatically renew your certificates every 2 months on the first Sunday of the month at 4am.
Your sensors need to be configured before starting the {{ic|lm_sensors}} service.


=== Systemd ===
{{note|This package is useless inside a VM.}}


{{hc|/etc/systemd/system/certbot.service|2=
{{bc|
[Unit]
sudo sensors-detect
Description=Let's Encrypt renewal
sudo systemctl enable --now lm_sensors
 
[Service]
Type=oneshot
ExecStart=/usr/bin/certbot renew --quiet --agree-tos
}}
}}


{{hc|/etc/systemd/system/certbot.timer|2=
Don't start {{ic|fail2ban}} or {{ic|sshd}} quite yet as they have configuration that needs to be done.
[Unit]
Description=Twice daily renewal of Let's Encrypt's certificates
 
[Timer]
OnCalendar=Sun *-2/12-1..7 04:00:00
RandomizedDelaySec=1h
Persistent=true
 
[Install]
WantedBy=timers.target
}}
 
=== Crontab ===
 
{{bc|0 4 1-7 2-12/2 0 /usr/bin/certbot renew}}
 
= E-mail =
 
= Roundcube =

Latest revision as of 03:39, 28 December 2019

Passwords & User Creation

Make sure root has a password.

Make sure you have a primary user set up.

sudo useradd -m -u <id -ge 1000> -g users -G wheel,games,video,audio,optical,storage,scanner,power <user>
sudo passwd <user>

/etc/fstab

Time Zone

sudo ln -sf /usr/share/zoneinfo/<region>/<city> /etc/localtime
sudo hwclock --systohc

Localization

Un-comment your desired locales in /etc/locale.conf, then run

sudo locale-gen

If you don't have the default /etc/locale.gen file:

sudo rm /etc/locale.gen
sudo pacman -Syu glibc

Edit /etc/locale.conf as you see fit

/etc/locale.conf
LANG=en_US.UTF-8
LANGUAGE=en_US
LC_COLLATE=POSIX
LC_MESSAGES=C
LC_CTYPE=en_US.UTF-8
LC_NUMERIC=en_US.UTF-8
LC_TIME=en_US.UTF-8
LC_MONETARY=en_US.UTF-8
LC_PAPER=en_US.UTF-8
LC_NAME=en_US.UTF-8
LC_ADDRESS=en_US.UTF-8
LC_TELEPHONE=en_US.UTF-8
LC_MEASUREMENT=en_US.UTF-8
LC_IDENTIFICATION=en_US.UTF-8

Set up /etc/vconsole.conf with a keymap and (optionally) a font:

/etc/vconsole.conf
KEYMAP=us
FONT=Lat2-Terminus16

Initramfs

Look for and edit the following lines:

/etc/mkinitcpio.conf
MODULES=([amdgpu|bochs_drm|cirrus|i915|nouveau|(nvidia nvidia_modeset nvidia_uvm nvidia_drm)] [ehci_pci usb_storage]>)
HOOKS=(base udev autodetect modconf block [zfs] filesystems keyboard fsck [encrypt] keymap consolefont)
COMPRESSION=lz4

Networking

Host Name

Make sure a host name is set in /etc/hostname

Then edit /etc/hosts

/etc/hosts
127.0.0.1	localhost.localdomain	locahost
::1		localhost.localdomain	localhost
127.0.1.1	<hostname>.localdomain	<hostname>

Static Addressing

Use systemd-networkd when a machine will use a static address without consulting a DHCP server.

IPv4 Only

/etc/systemd/network/network.network
[Match]
MACAddress=<mac-address>
[Network]
Address=<ipv4-address>/<mask>
DNS=<ipv4-address>
Gateway=<ipv4-address>
LinkLocalAddressing=no
IPv6AcceptRA=no

IPv4 & IPv6

/etc/systemd/network/network.network
[Match]
MACAddress=<mac-address>
[Network]
Address=<ipv6-address>/<mask>
DNS=<ipv6-address>
Gateway=<ipv6-address>
Address=<ipv4-address>/<mask>
DNS=<ipv4-address>
Gateway=<ipv4-address>

Dynamic Addressing

It's preferable to use connman or Network Manager for dynamic addresses as systemd-networkd doesn't play well with interfaces coming and going.

If you'd rather use systemd-networkd for DHCP:

/etc/systemd/network/network.network
[Match]
MACAddress=<mac-address>
[Network]
DHCP=yes
[DHCP]
UseMTU=true

Packages

Mirror List

Install and use reflector to automate the use and selection of mirrors.

sudo pacman -Syu reflector
sudo reflector -c <country> -p https -l 5 --sort rate --save /etc/pacman.d/mirrorlist

Yay

Make sure you have the base-devel group installed.

sudo pacman -Syu --needed base-devel git

Create a directory where AUR build files will go

sudo mkdir /var/lib/pacman/aur
sudo chmod 1777 /var/lib/pacman/aur
mkdir /var/lib/pacman/aur/$(whoami)

Build yay.

cd /var/lib/pacman/aur/$(whoami)
git clone https://aur.archlinux.org/yay.git
cd yay
makepkg -Ccisr

The create the configuration file.

~/.config/yay/config.json
{
	"aururl": "https://aur.archlinux.org",
	"buildDir": "/var/lib/pacman/aur/$USER",
	"editor": "nano",
	"editorflags": "",
	"makepkgbin": "makepkg",
	"makepkgconf": "",
	"pacmanbin": "pacman",
	"pacmanconf": "/etc/pacman.conf",
	"tarbin": "bsdtar",
	"redownload": "no",
	"rebuild": "no",
	"answerclean": "none",
	"answerdiff": "all",
	"answeredit": "",
	"answerupgrade": "0",
	"gitbin": "git",
	"gpgbin": "gpg",
	"gpgflags": "",
	"mflags": "",
	"sortby": "votes",
	"gitflags": "",
	"removemake": "yes",
	"requestsplitn": 150,
	"sortmode": 0,
	"completionrefreshtime": 7,
	"sudoloop": false,
	"timeupdate": false,
	"devel": true,
	"cleanAfter": false,
	"gitclone": true,
	"provides": true,
	"pgpfetch": true,
	"upgrademenu": true,
	"cleanmenu": true,
	"diffmenu": true,
	"editmenu": true,
	"combinedupgrade": false,
	"useask": false
}

General Utilities

These packages supplement the base system.

yay -Syu --needed adduser archey3 arj bind-tools bzip2 dmidecode dnsutils fail2ban git haveged htop hwdetect inxi iotop lshw lzop nano ncdu openssh p7zip pacman-contrib perl-rename pkgfile polkit ranger rsync strace sudo tmux unrar unzip vim whois zip

If you are not running inside a VM, you may also wish to add these packages:

yay -Syu hddtemp lm_sensors memtest86+ smartmontools

The havaged service can be enabled and started right away as no configuration is needed.

sudo systemctl enable --now haveged

Your sensors need to be configured before starting the lm_sensors service.

Note: This package is useless inside a VM.
sudo sensors-detect
sudo systemctl enable --now lm_sensors

Don't start fail2ban or sshd quite yet as they have configuration that needs to be done.