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 Converted over to bc/hc/ic templates
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|1=
# passwd <user>
# useradd -m -u <id -ge 1000> -g users -G wheel,games,video,audio,optical,storage,scanner,power <user>
# passwd <user>
}}


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


# ln -sf /usr/share/zoneinfo/<region>/<city> /etc/localtime
{{bc|1=
# hwclock --systohc
# ln -sf /usr/share/zoneinfo/<region>/<city> /etc/localtime
# 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|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|1=
# pacman -Syu glibc
# rm /etc/locale.gen
# 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 ==
== IPTables Firewall ==


# SIMPLE STATEFUL FIREWALL
{{hc|/etc/iptables/iptables.rules|2=
*filter
# SIMPLE STATEFUL FIREWALL
:INPUT DROP [0:0]
*filter
:FORWARD DROP [0:0]
:INPUT DROP [0:0]
:OUTPUT ACCEPT [100308:88697975]
:FORWARD DROP [0:0]
:TCP - [0:0]
:OUTPUT ACCEPT [100308:88697975]
:UDP - [0:0]
:TCP - [0:0]
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
:UDP - [0:0]
-A INPUT -i lo -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 8 -m conntrack --ctstate NEW -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m conntrack --ctstate INVALID -j DROP
-A INPUT -p icmp -m icmp --icmp-type 8 -m conntrack --ctstate NEW -j ACCEPT
-A INPUT -p udp -m conntrack --ctstate NEW -j UDP
-A INPUT -m conntrack --ctstate INVALID -j DROP
-A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -m conntrack --ctstate NEW -j TCP
-A INPUT -p udp -m conntrack --ctstate NEW -j UDP
-A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
-A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -m conntrack --ctstate NEW -j TCP
-A INPUT -p tcp -j REJECT --reject-with tcp-reset
-A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
-A INPUT -j REJECT --reject-with icmp-proto-unreachable
-A INPUT -p tcp -j REJECT --reject-with tcp-reset
-A INPUT -j REJECT --reject-with icmp-proto-unreachable
# OPEN NECESSARY PORTS HERE
 
# 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 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 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 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 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 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 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 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 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 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"
-A UDP -p udp -m udp --dport 64738 -j ACCEPT -m comment --comment "mumble udp"
COMMIT
COMMIT
}}


= Pacman =
= Pacman =
Line 145: Line 166:
== 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
# reflector -c <country> -p https -l 5 --sort rate --save /etc/pacman.d/mirrorlist


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


# pacman -Syu --needed git rsync openssh
{{bc|# pacman -Syu --needed git rsync openssh}}


== E-mail ==
== E-mail ==


# pacman -Syu --needed dovecot postfix rspamd swaks  
{{bc|# pacman -Syu --needed dovecot postfix rspamd swaks}}


== Nginx Web Server and Reverse Proxy ==
== Nginx Web Server and Reverse Proxy ==


# pacman -Syu --needed ca-certificates certbot-nginx mariadb nginx php-fpm
{{bc|# pacman -Syu --needed ca-certificates certbot-nginx mariadb nginx php-fpm}}


== Roundcube Web Mail ==
== Roundcube Web Mail ==


# pacman -Syu --needed pigeonhole roundcube
{{bc|# pacman -Syu --needed pigeonhole roundcube}}


= SSH Setup =
= SSH Setup =


Look for and edit the following lines in <code>/etc/ssh/sshd_config</code>:
Look for and edit the following lines in {{ic|/etc/ssh/sshd_config}}:
 
{{hc|/etc/ssh/ssd_config|2=
<nowiki>Port <port>
AddressFamily <any|inet|inet6>
ListenAddress <ip4-address>
ListenAddress <ip6-address>
 
LogLevel VERBOSE
 
PermitRootLogin prohibit-password
 
PubkeyAuthentication yes
 
PasswordAuthentication no
PermitEmptyPasswords no


Port <port>
ChallengeResponseAuthentication no
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:
UsePAM yes
AllowUsers <space-separated-list-of-users>


# systemctl enable --now sshd
AllowAgentForwarding no
AllowTcpForwarding no</nowiki>
}}
 
Then make sure the {{ic|sshd}} service is enabled and running:
 
{{bc|# systemctl enable --now sshd}}


= PHP-FPM =
= PHP-FPM =


Look for and edit the following lines in <code>/etc/php/php.ini</code>:
Look for and edit the following lines in {{ic|/etc/php/php.ini}}:
 
{{hc|/etc/php/php.ini|2=
[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


[PHP]
[Pdo_mysql]
open_basedir = /srv/http/:/home/:/tmp/:/usr/share/pear/:/usr/share/webapps/:/dev/urandom:/proc/meminfo
pdo_mysql.cache_size = 2000
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:
[Session]
session.save_path = "/tmp/php/sessions"


# systemctl enable --now php-fpm
[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 {{ic|php-fpm}} service is enabled and running:
 
{{bc|# systemctl enable --now php-fpm}}


= Nginx =
= Nginx =


First, edit <code>/etc/nginx/nginx.conf</code>:
First, edit {{ic|/etc/nginx/nginx.conf}}:
 
{{hc|/etc/nginx/nginx.conf|2=
<nowiki>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;


user http;
}</nowiki>
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.
Make the {{ic|sites-available}} and {{ic|sites-enabled}} directories.


# mkdir /etc/nginx/sites-{available,enabled}
{{bc|# mkdir /etc/nginx/sites-<nowiki>{available,enabled}</nowiki>}}


Then make a site available by creating <code>/etc/nginx/sites-available/<domain>.conf</code>:<br/>
Then make a site available by creating {{ic|/etc/nginx/sites-available/<domain>.conf}}:<br/>
(Remove the <code>#</code> after setting up Let's Encrypt.)
(Remove the {{ic|#}} after setting up Let's Encrypt.)


<pre>server {
{{hc|/etc/nginx/sites-available/<donmain>.conf|2=
<nowiki>server {
listen 80;
listen 80;
listen [::]:80;
listen [::]:80;
Line 426: Line 455:
}
}


}</pre>
}</nowiki>
}}


Enable the site
Enable the site


# ln -s ../sites-available/<domain>.conf /etc/nginx/sites-enabled/<domain>.conf
{{bc|# ln -s ../sites-available/<domain>.conf /etc/nginx/sites-enabled/<domain>.conf}}


Then create <code>index.php</code> for your new site.
Then create {{ic|index.php}} for your new site.


<pre><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
{{hc|/srv/http/<domain>/index.php|2=
<nowiki><!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">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<head>
Line 450: Line 481:


</body>
</body>
</html></pre>
</html></nowiki>
}}


Finally, make sure the <code>nginx</code> service is enabled and running:
Finally, make sure the {{ic|nginx}} service is enabled and running:


# systemctl enable --now nginx
{{bc|# systemctl enable --now nginx}}


= Let's Encrypt =
= Let's Encrypt =

Revision as of 09:55, 7 November 2019

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

/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

IPTables Firewall

/etc/iptables/iptables.rules
# 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

Mirror List

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

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

General Utilities

# pacman -Syu --needed git rsync openssh

E-mail

# pacman -Syu --needed dovecot postfix rspamd swaks

Nginx Web Server and Reverse Proxy

# pacman -Syu --needed ca-certificates certbot-nginx mariadb nginx php-fpm

Roundcube Web Mail

# pacman -Syu --needed pigeonhole roundcube

SSH Setup

Look for and edit the following lines in /etc/ssh/sshd_config:

/etc/ssh/ssd_config
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 sshd service is enabled and running:

# systemctl enable --now sshd

PHP-FPM

Look for and edit the following lines in /etc/php/php.ini:

/etc/php/php.ini
[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 php-fpm service is enabled and running:

# systemctl enable --now php-fpm

Nginx

First, edit /etc/nginx/nginx.conf:

/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
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 sites-available and sites-enabled directories.

# mkdir /etc/nginx/sites-{available,enabled}

Then make a site available by creating /etc/nginx/sites-available/<domain>.conf:
(Remove the # after setting up Let's Encrypt.)

/etc/nginx/sites-available/<donmain>.conf
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;
	}

}

Enable the site

# ln -s ../sites-available/<domain>.conf /etc/nginx/sites-enabled/<domain>.conf

Then create index.php for your new site.

/srv/http/<domain>/index.php
<!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>

Finally, make sure the nginx service is enabled and running:

# systemctl enable --now nginx

Let's Encrypt

# certbot --nginx

The nginx plugin will guide you and help automate the process.

Take note that the nginx configuration in this guide takes into account the settings suggested by certbot.

Automatic Renewal

These will automatically renew your certificates every 2 months on the first Sunday of the month at 4am.

Systemd

/etc/systemd/system/certbot.service
[Unit]
Description=Let's Encrypt renewal

[Service]
Type=oneshot
ExecStart=/usr/bin/certbot renew --quiet --agree-tos
/etc/systemd/system/certbot.timer
[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

0 4 1-7 2-12/2 0 /usr/bin/certbot renew

E-mail

Roundcube