Arch Post-Installation Checklist
Passwords & User Creation
Make sure root
has a password.
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> # passwd <user>
/etc/fstab
Time Zone
# ln -sf /usr/share/zoneinfo/<region>/<city> /etc/localtime # hwclock --systohc
Localization
Un-comment your desired locales in /etc/locale.conf
, then run
# locale-gen
If you don't have the default /etc/locale.gen
file:
# rm /etc/locale.gen # pacman -Syu glibc
Edit /etc/locale.conf
as you see fit
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:
KEYMAP=us FONT=Lat2-Terminus16
Initramfs
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]>) 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
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
[Match] MACAddress=<mac-address> [Network] Address=<ipv4-address>/<mask> DNS=<ipv4-address> Gateway=<ipv4-address> LinkLocalAddressing=no IPv6AcceptRA=no
IPv4 & IPv6
[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:
[Match] MACAddress=<mac-address> [Network] DHCP=yes [DHCP] UseMTU=true
IPTables Firewall
# SIMPLE STATEFUL FIREWALL *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
# pacman -Syu reflector # reflector -c <country> -p https -l 5 --sort rate --save /etc/pacman.d/mirrorlist # pacman -Syu
SSH Setup
Look for and edit the following lines:
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
Nginx
# pacman -Syu nginx
Then edit /etc/nginx/nginx.conf
:
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 events { multi_accept on; worker_connections 1024; # number of parallel or concurrent connections per worker_processes worker_cpu_affinity auto; 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) } 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; client_max_body_size 16M; # 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 1d; ssl_session_cache shared:SSL:10m; ssl_session_tickets off; # Diffie-Hellman parameter for DHE ciphersuites ssl_dhparam /etc/nginx/dhparam.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 10M; #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" types_hash_max_size 3072; ## 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'; ## Deny access to any host other than (www.)mydomain.com. Only use this ## option is you want to lock down the name in the Host header the client sends. #server { # server_name ""; #default # return 444; #} # load configs include /etc/nginx/conf.d/*.conf; include sites-enabled/*.conf; }