Skip to content

Instantly share code, notes, and snippets.

@erikw
Last active May 12, 2022 21:54
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save erikw/b005e31c2c01730fdc8d0aaa8ede53e5 to your computer and use it in GitHub Desktop.
Save erikw/b005e31c2c01730fdc8d0aaa8ede53e5 to your computer and use it in GitHub Desktop.
A log of how I configured FreeBSD spring 2018 on my Intel NUC Dawson Canyon NUC7i3DNH2
#!/usr/bin/env bash
# A log of how I configured FreeBSD spring 2018 on my Intel NUC Dawson Canyon NUC7i3DNH2E (NUC7i3DNH).
# Modeline {
# vi: foldmarker={,} foldmethod=marker foldlevel=0 tabstop=4
# }
# Links {
# FreeBSD vs Linux:
# http://www.over-yonder.net/~fullermd/rants/bsd4linux/01
# https://forums.freebsd.org/threads/freebsd-vs-linux-10-points-of-superiority-including-motiv.41750/
# }
# }
# UEFI {
# * Reboot, press F2 to enter BIOS.
# * Home > Set system time.
# * Home > Devices > Onboard Devices: disalbe Bluetooth.
# * Home > Security > Set supervisor password
# * Home > Boot > enable "Legacy boot" to be able to boot Linux images.
# * Home > Boot > Boot Configuration > check "Boot USB devices first"
# * Home > Power > check "Low power enabled".
# * Home > Power > "After Powerfailure" -> "Last State", so that the server is restarted if it was powwerd on during AC failure.
# ** NOTE it seems like my TV monitor is not activated when restarted from last state, so no display function.
# * Home > Power > "Button LED" -> Power State
# * Home > Power > "SO Indicator Brightness" -> OFF, so that I can sleep without having the LED in my face.
# * Home > Power > "Wake on LAN from S4/S5" -> "Power On - Normal Boot", to enable WoL.
# NOTE don't set this until after installing the OS and apps, as some juice can be needed to compile everything.
# }
# Install FreeBSD {
# Burn ISO {
# Download amd64 image from https://www.freebsd.org/where.html#download
cd ~/dl/
curl -OJ https://download.freebsd.org/ftp/releases/amd64/amd64/ISO-IMAGES/11.1/FreeBSD-11.1-RELEASE-amd64-bootonly.iso.xz
curl -OJ https://download.freebsd.org/ftp/releases/amd64/amd64/ISO-IMAGES/11.1/CHECKSUM.SHA512-FreeBSD-11.1-RELEASE-amd64
unxz FreeBSD-11.1-RELEASE-amd64-bootonly.iso.xz
# Verify checksum
sha512sum -c CHECKSUM.SHA512-FreeBSD-11.1-RELEASE-amd64  1  0
# Burn image to USB stick.
sudo dd if=./FreeBSD-11.1-RELEASE-amd64-bootonly.iso of=/dev/sdc bs=1M status=progress
# }
# FreeBSD installer {
# Handbook: https://www.freebsd.org/doc/handbook/
# * Reboot, press F10 to enter boot menu and select my USB stick.
# * Select "Boot Multi User"
# * Select "<Install>"
# * Continue with defalt US keymap
# * Set hostname to "server-name.erikw.me"
# * Chose componentes to install:
# - doc
# - lib32
# - ports
# * Accept default IPv4 DHCP & IPv6 SLAAC settings for default NIC.
# * Select a German mirror for the distributions.
# * For disk partition, select "Auto (ZFS). Select:
# - Pol Type/Disks: stripe (no redundance), and select the main disk ada0.
# - Pool name: zroot (default)
# - Force 4k sectors: yes (default)
# - Encrypted: yes
# - Partition Scheme: GPT (BIOS + UEFI)
# - Swap size: 4g
# - Mirror swap: NO
# - Encrypted Swap: YES
# then select ">>> Install: Proceed with installtion".
# * Enter a strong encryption password.
# * Enter strong ~root user password.
# * Select German timezone
# * Select theser services to start at boot:
# - local unbound DNS caching
# - sshd
# - ntpd
# - powerd
# - dumpdev
# * Select security features:
# - Clean /tmp on system start
# * Create new user ~erikw, and add to additional group wheel so I can become super user.
# * Exit to apply changes
# * Reboot
#
#
#
#
# SKIPPED manual partition {
# SKIP manual parition - too complex and the installer does a good job.
## Create ZFS pools
# Reference: https://www.freebsd.org/doc/handbook/zfs-zpool.html
#
## Create ZFS datasets
# Reference: https://www.freebsd.org/doc/handbook/zfs-zfs.html
# |------+------------+------+-----------+---------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
# | pool | mountpoint | size | encrypted | options | notes |
# |------+------------+------+-----------+---------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
# | tank | / | - | yes | | |
# | tank | /home | - | yes | | |
# | ? | /boot | ? | no | | |
# | ? | /tmp | ? | yes | | |
# | ? | swap | ? | yes | | should be 2x RAM = 2*16GB. However this old recommendation seems outdated and 1-1.5xRAM seems to be enought, https://askubuntu.com/questions/49109/i-have-16gb-ram-do-i-need-32gb-swap |
# |------+------------+------+-----------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
#
#
# Encrytp with Geli
# https://www.freebsd.org/doc/handbook/disks-encrypting.html
kldstat
kldload geom_eli
# }
# }
# }
# System conf {
# NOTE scroll up in the console by pressing Scroll Lock then Page Up/Down.
# NOTE switch between virtual consoles with ALT + F1-8
# ~root configuration {
# Change from defautl csh to sh for root:
chsh -s /bin/sh root
cat << EOF >> ~/.profile
# Custom below:
# Make sure /usr/local/ comes before /usr, so installed ports like unbound can override system default ones.
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:~/bin
export PATH
#
# Use vi mode
set -o vi
# Set prompt
export PS1='root@\h \W\$ '
# Aliases
alias ls='ls -F' # Display / after directories
alias ll='ls -l'
alias vi=vim
EOF
# Fix tmux
cat << EOF > /root/.tmux.com
set-option -g status-keys vi # Use Vi bindings in tmux command prompt.
set-option -g history-limit 131072 # Number of terminal lines per window to keep. (2^17)
set-window-option -g mode-keys vi # Use Vi bindings in copy and choice mode.
set-window-option -g monitor-activity on # Monitor windows for activity.
unbind-key C-b # Unbind default prefix key.
set-option -g prefix C-a # Seconday prefix key like GNU Screen.
bind-key a send-prefix # Send ^A.
bind-key b send-prefix # Send ^B.
bind-key C-a last-window # Toogle last window.
EOF
# }
# ~toor configuration {
# Use toor for day-to-day tasks, using non-standard shell, as recommended at https://www.freebsd.org/doc/en/books/faq/security.html#idp60349640
# Change back to default shell for root
chsh -s /bin/tcsh root
# Set password for user
passwd toor
# Change shell to zsh
chsh -s /usr/local/bin/zsh toor
# Make minimal zshrc
cat << EOF > ~/.zshrc
source $HOME/.profile
autoload -U colors && colors
autoload -Uz promptinit
promptinit
prompt suse
zstyle ':completion:*' completer _expand _complete _ignored _correct _approximate
zstyle ':completion:*' menu select
zstyle ':completion:*' squeeze-slashes true
autoload -Uz compinit
compinit -C
export HISTFILE=~/.zsh_histfile
export HISTSIZE=1000000
export SAVEHIST=1000000
unsetopt correct correctall
EOF
# Try it out
su toor
id
exit # to rootsh
# Make shell alias for ~erikw like: alias sudo='sudo -u toor'.
# }
# Disks {
su -
## ZFS config
# If the installer did not already set compression, do so on the whole pool, so the dataset inherits it.
# The default poolname is zroot, which can be found with $(zpool list).
zfs get compression
zfs set compression=lz4 zroot
# ZFS deduplication seems not be needed as $(zpool list) for zroot has 1.0 in deduplication factor (no duplicaes) for me.
# https://constantin.glez.de/2011/07/27/zfs-to-dedupe-or-not-dedupe/
# https://www.freebsd.org/doc/handbook/zfs-zfs.html#zfs-zfs-deduplication
# Set reserved space on root and home dataset so we never run out of disk here due to other datasets eating space.
# https://www.freebsd.org/doc/handbook/zfs-zfs.html#zfs-zfs-reservation
zfs set reservation=16G zroot/ROOT/default
zfs set reservation=16G zroot/usr/home
# Scrub pool -- do this form time to time
zpool scrub zroot
zpool status zroot
# Make a copy of the encryption key needed to unlock the zroot pool with geli
cp /boot/encryption.key /home/erikw/
chmod erikw /home/erikw/encryption.key
# TO view swap setup
grep swap /etc/fstab
swapctl -lg
# ZFS snapshots {
# Reference: https://www.freebsd.org/doc/handbook/zfs-zfs.html
# Create recursive snapshot in the entire pool
zfs snapshot -r zroot@snap0_test
zfs list -t all
zfs list -t snapshot
# See stats against original version
touch /home/erikw/test
zfs list -rt all zroot/usr/home
# See diff against original
zfs diff zroot/usr/home@snap0_test
# Diff 2 snapshots
zfs diff zroot/usr/home@snap0_test zroot/usr/home@snap1_test
# Rollback
rm /home/erikw/.viminfo
zfs diff zroot/usr/home@snap0_test
zfs rollback zroot/usr/home@snap0_test
# Restore individual files
ls /.zfs/snapshots
cp /usr/home/.zfs/snapshot/snap0_test/erikw/.viminfo /home/erikw/
# Remove snapshot
zfs destroy -nv -r zroot@snap0_test # Dry run
zfs destroy -r zroot@snap0_test
zfs list -t snapshot
# Automatic snapshotting with zfstools {
# Reference: http://eduardosanchez.me/2015/08/31/zfs-automatic-snapshots/
# Reference: https://blather.michaelwlucas.com/archives/2140
pkg install zfstools
# Set which dataset to automatically snapshot with a ZFS property.
# Start by enabling it on the whole pool.
zfs set com.sun:auto-snapshot=true zroot
# See current enabled datasets for auto snapshotting:
zfs get com.sun:auto-snapshot
# Now disable specific datasets in the pool.
zfs list
zfs set com.sun:auto-snapshot=false zroot/tmp
zfs set com.sun:auto-snapshot=false zroot/usr/ports
zfs set com.sun:auto-snapshot=false zroot/usr/src
zfs set com.sun:auto-snapshot=false zroot/var/audit
zfs set com.sun:auto-snapshot=false zroot/var/crash
zfs set com.sun:auto-snapshot=false zroot/var/log
zfs set com.sun:auto-snapshot=false zroot/var/tmp
# Set up activation through cron:
cat << EOF > /etc/cron.d/zfs-auto-snapshot
SHELL=/bin/sh
PATH=/etc:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
# Order of crontab fields
# minute hour mday month wday command
# Reference: https://www.freebsd.org/doc/handbook/configtuning-cron.html
# Reference: crontab(5).
#15,30,45 * * * * root /usr/local/sbin/zfs-auto-snapshot frequent 4
0 * * * * root /usr/local/sbin/zfs-auto-snapshot hourly 24
7 0 * * * root /usr/local/sbin/zfs-auto-snapshot daily 7
14 0 * * 7 root /usr/local/sbin/zfs-auto-snapshot weekly 4
28 0 1 * * root /usr/local/sbin/zfs-auto-snapshot monthly 7
EOF
# Lets try so it works:
/usr/local/sbin/zfs-auto-snapshot hourly 24
zfs list -rt snapshot zroot/usr/home
#
# }
# }
# Change GELI passphrase {
# See geli(8)
# At some point I got tired of the boot passphrase for encrypted root disk, because my server now hosts essential network features like DHCP server and DNS server, and it already happended 2 times that the network was down for many days because I was not home to restart the server. Thus I decided to get rid of the manually entered passphrase for now.
geli status
geli list
#geli setkey -n 0 -K /bootpool/boot/encryption.key -P /dev/ada0p5
# NOPE this is what one would think to work, to use -P to not use a passphrase. However it turns out that even if you use -P, and disable passphrase collection in loader.conf, geli will still prompt for password during boot.
# However, it turns out that if we create a BLANK password, geli will apparently try a blank password during boot before prompting the user.
geli setkey -n 0 -k /bootpool/boot/encryption.key -K /bootpool/boot/encryption.key /dev/ada0p5
# Make a backup and store in laptop ~/bak/server-name_nuc/
geli backup /dev/ada0p5 geli_backup_ada0p5_2018-08-02
# Disable collection passphrase in early boot for later usage.
patch << EOF
--- /bootpool/boot/loader.conf
- geom_eli_passphrase_prompt="YES"
+ # Disabelded collection of passphrase during boot for later geli disk encryption, as I only use keyfile now (above).
+ #geom_eli_passphrase_prompt="YES"
+ geom_eli_passphrase_prompt="NO"
EOF
# }
# }
# Bootloader {
# If messing up variables in here, froom the boot menu chose to enter the boot loader, then type "unset var" to remove value set in conf file.
cat << EOF >> /boot/loader.conf
# Custom below:
# Reduce boot menu timeout from 10 seconds to 1. Pause the autoboot by pressing Space.
# Settings to 0 does not allow pause with space.
# See loader(8).
autoboot_delay=1
EOF
# }
# rc.conf {
cat << EOF > /etc/rc.conf
# See default values in /etc/defaults/rc.conf
# By default everything was set up here in /etc/rc.conf. This is messy, so I migrated out stuff to individual files in /etc/rc.conf.d to the corresponding /etc/rc.d files
# First disable everything in this file, but keep dumpdev.
# https://github.com/JoeKun/freebsd-configuration/tree/master/etc/rc.conf.d
# https://www.rhyous.com/2012/04/12/decoupling-settings-from-etcrc-conf-in-freebsd/
# http://quiddle.net/post/77406007305/using-rcconfd-in-freebsd
# Set dumpdev to "AUTO" to enable crash dumps, "NO" to disable
# Used by both /etc/{savecore,dumpon}
dumpdev="AUTO"
EOF
# Now create the other files with migrated values from the rc.conf file:
cat << EOF > /etc/rc.conf.d/cleartmp
clear_tmp_enable="YES"
EOF
cat << EOF > /etc/rc.conf.d/hostname
hostname="server-name.erikw.me"
EOF
cat << EOF > /etc/rc.conf.d/local_unbound
local_unbound_enable="YES"
EOF
cat << EOF > /etc/rc.conf.d/network
ifconfig_em0="DHCP"
ifconfig_em0_ipv6="inet6 accept_rtadv"
EOF
cat << EOF > /etc/rc.conf.d/ntpd
ntpd_enable="YES"
EOF
cat << EOF > /etc/rc.conf.d/powerd
powerd_enable="YES"
EOF
cat << EOF > /etc/rc.conf.d/sshd
sshd_enable="YES"
EOF
cat << EOF > /etc/rc.conf.d/zfs
zfs_enable="YES"
EOF
cat << EOF > /etc/rc.conf.d/syslogd
syslogd_enable="YES"
EOF
cat << EOF >> /etc/rc.conf.d/syscons
# Increase vt(4) font size. Try out the fonts with vidfont(1).
allscreens_flags="-f vgarom-16x32"
# Increase keyboard repeat rate, in the form delay.speed. Default is 500.126.
# See kbdcontrol(1), and test with $(kbdcontrol -r speed.delay).
keyrate=350.20
EOF
# Save some energy by configuring powerd to use adaptive profile.
cat << EOF > /etc/rc.conf.d/powerd
powerd_enable="YES"
# User more power saving options in powerd(8)
powerd_flags="-a adaptive"
EOF
# }
# Keymaps {
# Map Capslock to Escape
# Reference: http://ake.in.th/2015/04/17/remap-capslock-to-ctrl-on-freebsd/
# Try existing layouts
kbdmap
# Make a copy of US layout
cd /usr/share/vt/keymaps/
cp us.kbd us.custom.kbd
chmod 744 us.custom.kbd
# Change key 58 to produce escape:
patch << EOF
--- us.custom.kbd
- 058 clock clock clock clock clock clock clock clock O
+ 058 esc esc esc esc esc esc esc esc O
EOF
chmod 444 us.custom.kbd
# Add the new keymap to the index:
chmod 744 INDEX.keymaps
echo "# Custom below:" >> INDEX.keymaps
echo "us.custom.kbd:en:United States of America Custom" >> INDEX.keymaps
chmod 444 INDEX.keymaps
# Try the layout
kbdcontrol -l us.custom.kbd
# Load this keymap by default:
cat << EOF >> /etc/rc.conf.d/syscons
# Use my custom keyboard layot defined in /usr/share/vt/keymaps/{us.custom.kbd,INDEX.keymaps}.
keymap="us.custom"
EOF
# }
# SSH {
# https://www.freebsd.org/doc/handbook/openssh.html
#
# Make sure sshd is enabled in /etc/rc.conf: sshd_enable="YES"
# and running $(service sshd status)
#
#
#
# sshd_config(5)
# Verify default config with
sshd -T | grep -i PermitRootLogin
# Set options
cat << EOF >> /etc/ssh/sshd_config
### Custom Below ###
# Having DNS on make ssh login very slow.
# Reference: http://jrs-s.net/2017/07/01/slow-ssh-logins/
# Reference: https://unix.stackexchange.com/questions/56941/what-is-the-point-of-sshd-usedns-option
UseDNS no
# Don't allow root logins:
PermitRootLogin no
# Misc
X11Forwarding no
Banner /etc/ssh/banner
EOF
echo "Welcome!" > /etc/ssh/banner
service sshd reload
# }
# motd {
# Set custom stuff in /etc/motd.tail
mkdir /usr/local/sbin
cat << EOF >> /usr/local/sbin/motd_gen.sh
#!/usr/bin/env sh
cp /etc/motd /etc/motd.bak
uname -mnrs > /etc/motd
cat /etc/motd.tail >> /etc/motd
EOF
chmod 744 /usr/local/sbin/motd_gen.sh
# laptop$ scp ~/doc/tech/server-name/motd.tail server-name:
mv /home/erikw/motd.tail /etc/
# }
# Time {
# It looks like the default ntp configuration should be able to pick ranom servers, but this does not seem to work, thus
# Reference: https://www.freebsd.org/doc/handbook/network-ntp.html
cat << EOF >> /etc/ntp.conf
# German servers
# Reference: http://www.pool.ntp.org/zone/de
server 0.de.pool.ntp.org
server 1.de.pool.ntp.org
server 2.de.pool.ntp.org
server 3.de.pool.ntp.org
# Comment all default restric-lines, and enable the deny rules for all ntp queries against this machine:
restrict default ignore
restrict -6 default ignore
EOF
# Set up timezone with
tzsetup
# If timezone is right, but time is wrong, then you might need to update timezone in kernel:
# Reference: https://forums.freebsd.org/threads/wrong-time-but-right-timezone.56345/
adjkerntz -i
# }
# Firewall: ipfw {
# Reference: https://www.freebsd.org/doc/handbook/firewalls-ipfw.html
# Reference: https://www.digitalocean.com/community/tutorials/recommended-steps-for-new-freebsd-10-1-servers
# First, in case of fuck-up, disable the default deny-all
cat << EOF >> /boot/loader.conf
# Temporarily disable ipfs's default deny-all rule, when configuiring ipfw to not be locked out of the system in case of fuck-up.
# NOTE by default have this line out-commented!
kenrel_options=net.inet.ip.fw.default_to_accept="1"
EOF
cat << EOF > /etc/rc.conf.d/ipfw
firewall_enable="YES"
# Logfile is /var/log/security
firewall_logging="YES"
# My custom firewall script, which first uses /etc/rc.firewall
firewall_script="/etc/ipfw.rules"
# See /etc/rc.firewall for workstation variables meaning.
firewall_type="workstation"
# User either port/proto or name from /etc/services
# NOTE let ssh be controlled by knockd instead.
#firewall_myservices="22/tcp"
#firewall_myservices="ssh"
firewall_allowservices="any"
firewall_logdeny="YES"
EOF
cat << EOF >> /etc/rc.conf
# /etc/rc.firewall does not read /etc/rc.conf.d/ipfw but this file, which is a scam. It should!
if [ -e /etc/rc.conf.d/ipfw ]; then
. /etc/rc.conf.d/ipfw
fi
EOF
# Create my own ipfw script to have custom rules:
cat << EOF > /etc/ipfw.rules
#!/bin/sh
# Custom ipfw script.
# See: https://www.freebsd.org/doc/handbook/firewalls-ipfw.html
## Flush out the list before we begin.
#ipfw -q -f flush
# Start by sourcing the default scrip, we only want to append to this one.
. /etc/rc.firewall
## Set rules command prefix
cmd="ipfw -q add"
pif="em0" # interface name of NIC attached to Internet
# Mosh
# Reference: https://github.com/ptudor/freebsd-install/blob/master/etc/ipfw.rules
$cmd 24110 allow udp from any to any 60000-61000 in keep-state
# Knockd workaround; allow ssh from local network.,
# From specific host:
#$cmd 900 allow tcp from any to me src-ip 192.168.178.21 dst-port 22
# From whole LAN:
# Fritz.box local net
$cmd 900 allow tcp from any to me src-ip 192.168.178.0/24 dst-port 22
# server-name local net
$cmd 900 allow tcp from any to me src-ip 10.0.0.0/8 dst-port 22
EOF
service ipfw start
# Show loaded configs:
ipfw show
# Now enable the default deny-all rule in /boot/loader.conf
# }
# Firewall: pf {
# ipfw was too complex to config for openvpn nat..
# Reference: https://www.freebsd.org/doc/handbook/firewalls-pf.html
service ipfw stop
cat << EOF >/etc/rc.conf.d/pf
pf_enable="YES"
#pf_flags=""
EOF
# Logging
cat << EOF >/etc/rc.conf.d/pflog
pflog_enable="YES"
EOF
service pflog start
cat << EOF >/etc/pf.conf
# pf port filter conf.
# See pf.conf(5)
# == Macros ==
# Names from /etc/services can be used
ext_if = "em0"
vpn_if = "tun0"
local_subnet = "10.0.0.0/8"
vpn_subnet = "172.16.123.0/24"
# The direct network attached to this nic.
localnet = $ext_if:network
srv_znc = "6677"
srv_taskd = "53589"
srv_webmin = "10000"
srv_cupsd_admin = "631"
srv_samba = "hosts2-ns netbios-ns netbios-dgm netbios-ssn microsoft-ds"
srv_mosh = "60000:61000"
# Ports to open for incoming traffic.
# ssh - let this be controlled by knockd instead.
# ftpd - this enabled active mode, where server opens the data channel to the client. Use this so we don't have to open incomming trafic on the high level ports for passive. mode. Reference: https://stackoverflow.com/questions/1699145/what-is-the-difference-between-active-and-passive-ftp and https://forums.freebsd.org/threads/ftp-ipfw-passive-rules.34618/
# domain - DNS local caching
tcp_ingress = "{" \
domain \
ftp \
$srv_cupsd_admin \
$srv_samba \
$srv_taskd \
$srv_webmin \
$srv_znc \
"}"
# domain - DNS local caching
# isc-dhcpd - my DHCP server
# openvpn - OpenVPN server
udp_ingress = "{" \
bootps \
domain \
openvpn \
$srv_mosh \
"}"
# == Options ==
# Don't filter at all on loop back interface. Needed for unbound DNS server to work.
set skip on lo
# Which interface to log
set loginterface $ext_if
# == Translation ==
# OpenVPN NAT
# Allow traffic to flow from virtual network to my local (and thus Internet)
nat on $ext_if inet from $vpn_subnet to any -> $ext_if
# == Filtering ==
# By default, block everything.
block in all
# Log all dropped incoming packages.
block drop log on $ext_if all
# Allows connections created by this system to pass out, while retaining state information on those connections. This state information allows return traffic for those connections to pass back and should only be used on machines that can be trusted.
pass out all keep state
pass in on $ext_if proto tcp to ($ext_if) port $tcp_ingress
pass in on $ext_if proto udp to ($ext_if) port $udp_ingress
# Knockd
# Always allow ssh from local network, then open for externals when knocking succeeds.
pass in on $ext_if proto tcp from $local_subnet to $ext_if port ssh
# Create a separate IP address table for knockd addresses. Entires in this table gains ssh access.
# knockd uses pfctl to modify this talbe.
#Inspect the contents wit $(pfctl -t knockd -T show)
table <knockd> persist
pass in on $ext_if inet proto tcp from <knockd> to ($ext_if) port ssh flags S/SA keep state
# Allow ICMP (mostly ping) from peers in the same net.
pass inet proto icmp from $localnet to any keep state
pass inet proto icmp from any to $ext_if keep state
# Allow outgoing traceroute
pass out on $ext_if inet proto udp from any to any port 33433 >< 33626 keep state
EOF
# Start pf
pfctl -e
# Test rules
pfctl -nf /etc/pf.conf
# Load rules for real
pfctl -f /etc/pf.conf
# The best reload:
pfctl -f /etc/pf.conf && pfctl -sr
# Check conf for errors
pfctl -vnf /etc/pf.conf
service pf onereload
# Flush all configs and reload
# NOTE this kicks ssh connection of, and you have to connect again.
pfctl -F all -f /etc/pf.conf
# View final rules:
pfctl -sr
# Stop pf
pfctl -d
# Test from other host:
# Ports 1-100
# laptop$ nmap -F 10.0.0.2
# Ports 1-65535
# laptop$ nmap -p- 10.0.0.2
# A single port:
# laptop$ nmap -p 22 10.0.0.2
# Connect to random port
# laptop$ netcat srv 123
# To view logs, use tcpdump as the log is binary
tcpdump -r /var/log/pflog
# Or with more info like wich rules were applied
tcpdump -n -e -ttt -r /var/log/pflog
# To view live, use the pflog interface
tcpdump -n -e -ttt -i pflog0
# When config esp. ssh works:
service pf start
# }
# knockd {
# http://www.zeroflux.org/projects/knock
# Note that it adds only obfuscation and possibly security vulnerabilities: http://bsdly.blogspot.de/2012/04/why-not-use-port-knocking.html https://en.wikipedia.org/wiki/Port_knocking#Security_considerations
# Now install and conf knockd
pkg install knock
mkdir /usr/local/etc/rc.conf.d/
cat << EOF > /usr/local/etc/rc.conf.d/knockd
knockd_enable="YES"
EOF
cp /usr/local/etc/knockd.conf.sample /usr/local/etc/knockd.conf
# Edit knockd.conf to look like:
cat << EOF > /usr/local/etc/knockd.conf
[options]
logfile = /var/log/knockd.log
interface = em0
#[openSSH]
# sequence = ...
# seq_timeout = 10
# #command = /sbin/ipfw -q add pass proto tcp src-ip %IP% dst-port 22
# # Not giving the rule a number appends it to the last rule. This is alreay too late as rules are evaluated from top to botton. So let's chose a lower range.
# command = /sbin/ipfw -q add 1000 pass proto tcp src-ip %IP% dst-port 22
# tcpflags = syn
[opencloseSSH]
sequence = ....
seq_timeout = 10
tcpflags = syn
start_command = /sbin/ipfw -q add 1000 pass proto tcp src-ip %IP% dst-port 22
# Close connection after 30m automatically.
cmd_timeout = 1800
stop_command = /sbin/ipfw -q delete 1000 pass proto tcp src-ip %IP% dst-port 22
[closeSSH]
sequence = ....
seq_timeout = 10
#command = /sbin/ipfw -q delete pass proto tcp src-ip %IP% dst-port 22
# The delete command must match the number from when adding it.
command = /sbin/ipfw -q delete 1000 pass proto tcp src-ip %IP% dst-port 22
tcpflags = syn
EOF
# set interface=em0
service knockd start
# Now configure my router to let TCP packages on these ports through to my router.
# Name rules like:
# knock-ssh-open: #1
# knock-ssh-open: #2
# knock-ssh-open: #3
# knock-ssh-close: #1
# knock-ssh-close: #2
# knock-ssh-close: #3
# Tail the log before trying
tail -f /var/log/knokcd.log
# laptop$ knock 10.0.0.2 x y z
# laptop$ ssh 10.0.0.2
# Verify with nmap from another computer that port 22 is hidden:
# laptop $ nmap -Pn -p server-name.erikw.me
# If it's working the state is "filtered", if not "open".
## Client notes
# On Android "Port Knocker", decrease the delay between packages to 300ms. Otherwise it seems like they don't arrive.
# }
# sudo {
# Reference: https://www.freebsd.org/doc/handbook/security-sudo.html
pkg install sudo
visudo # Uncomment so wheel can use sudo & enable logging per user:
# %wheel ALL=(ALL) ALL
#
## Uncomment to enable logging of a command's output, except for
## sudoreplay and reboot. Use sudoreplay to play back logged sessions.
#Defaults log_output
#Defaults!/usr/bin/sudoreplay !log_output
#Defaults!/usr/local/bin/sudoreplay !log_output
#Defaults!REBOOT !log_output
cat << EOF > /usr/local/etc/sudoers.d/99_mystuff
# My own sudo settings.
# Set cached password timeout in minutes.
Defaults:USER_NAME timestamp_timeout=16
# Single password cache for user.
Defaults !tty_tickets
# Insult when bad password is entered.
Defaults insults
# Paths so users don't have to use full paths.
Defaults secure_path = "/bin:/sbin:/usr/bin:/usr/sbin"
# Dir needed for sudoreplay logging set up in /usr/local/etc/sudoers.
Defaults iolog_dir=/var/log/sudo-io/%{user}
# Command groups.
Cmnd_Alias CMDS_POWER = /sbin/halt, /sbin/poweroff, /sbin/shutdown, /sbin/reboot
# Let power users issue power commands.
%power ALL = NOPASSWD: CMDS_POWER
EOF
pw group add power
pw group show power
pw groupmod power -M erikw
pw group show power
# }
# Dyndns with ddclient {
# NOTE with ssmtp, sending of email seems to work only when executing myself on commandline, some times, and not when running as a service.
pkg install ddclient
cp /usr/local/etc/ddclient.conf.sample /usr/local/etc/ddclient.conf
cat << EOF > /usr/local/etc/ddclient.conf
daemon=300 # check every 300 seconds
syslog=yes # log update msgs to syslog
mail=root # mail all msgs to root
mail-failure=root # mail failed update msgs to root
pid=/var/run/ddclient.pid # record PID in file.
ssl=yes # use ssl-support. Works with
# Source: https://support.loopia.se/wiki/ddclient-linux-och-unix/
##
## LoopiaDNS (www.loopia.se/loopiadns/)
## (supports variables: wildcard,mx,backupmx)
##
protocol=dyndns2
custom=yes
server=dyndns.loopia.se
use=web, web=dyndns.loopia.se/checkip,
web-skip='Current IP Address:'
login=...
password=...
wildcard=yes
erikw.me
EOF
cat << EOF > /usr/local/etc/rc.conf.d/ddclient
ddclient_enable="YES"
EOF
chmod 500 /usr/local/etc/ddclient.conf
service ddclient start
# Try update myself with
ddclient --force
# }
# Wireless NIC {
# Reference: https://www.freebsd.org/doc/handbook/config-network-setup.html
# Show modules currently loaded:
kldstat
# Available kernels at
ls /boot/kernel/
# My NUC's wireless card is "Integrated Wireless‡: Intel® Wireless-AC 8265 (IEEE 802.11ac 2x2)"
# Unfortunately iwm(4) does not list support for this card. But code for this seems to be merged
# https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=220229
# and is said to be included in upcoming FreeBSD 12.0
# If there would be support, I would probably load it like this:
kldload if_iwm
kldload iwm8000Cfw
ifconfig
pciconf -l | grep iwm
# and add to /etc/loader.conf:
# if_iwm_load="YES"
# iwm7260fw_load="YES"
# Reference: https://forums.freebsd.org/threads/intel-7260.55061/
# * Then connect to a WiFi:
# Reference: https://www.freebsd.org/doc/handbook/network-wireless.html
# Reference: https://www.freebsd.org/cgi/man.cgi?query=iwm&sektion=4&manpath=freebsd-release-ports
# Create the interface
ifconfig wlan createwlandeviwm0 up
ifconfig wlan0 scan
# In case of fuck-up, delete it with.
ifconfig wlan0 destroy
cat << EOF >> /etc/rc.conf.d/network
# WLAN
wlans_iwm0="wlan0"
#ifconfig_wlan0="WPA DHCP"
ifconfig_wlan0="WPA 10.0.0.18 netmask 255.0.0.0"
EOF
cat << EOF >> /etc/wpa_supplicant.conf
network={
ssid="westnet"
key_mgmt=WPA-PSK
scan_ssid=1
psk="<password>"
}
EOF
# Try it out
service netif restart
ifconfig wlan0
# Try WPA supplicant manually with
wpa_supplicant -i wlan0 -c /etc/wpa_supplicant.conf -dd
# NOTE must also update firewall to apply same rule to wlan NIC as to eth NIC.
# NOTE must also update router forwarding rules.
# NOTE it did not work with westnet when channel 13 was used, but worked when moved to channel 8.
# }
# Rootkit Hunter {
pkg install rkhunter
# Run manually:
rkhunter --check-all --skip-keypress
cat << EOF >> /etc/periodic.conf
# rkhunter
# Enable daily rkhunter run. Commands comes from the post-install message in pkg-install
daily_rkhunter_update_enable="YES"
daily_rkhunter_update_flags="--update --nocolors"
# Run rkhunter as a part of the daily security check
daily_rkhunter_check_enable="YES"
daily_rkhunter_check_flags="--checkall --nocolors --skip-keypress"
EOF
# Config so known problems are not shown as warnings
# in /usr/local/etc/rkhunter.conf, set
# ALLOW_SSH_ROOT_USER=no
cat << EOF >>/usr/local/etc/rkhunter.conf
#### CUSTOM BELOW ###
PWDLESS_ACCOUNTS='ftp pcguest'
ALLOWHIDDENDIR=/etc/.git
ALLOWHIDDENFILE=/etc/.gitignore
EOF
# Property database must be updated with new values:
rkhunter --propupd
# }
# Audit logging {
# Reference: https://www.freebsd.org/doc/handbook/audit-config.html
# * Start at boot.
cat << EOF > /usr/local/etc/rc.conf.d/auditd
auditd_enable="YES"
EOF
# Set selection what to audit, and how much disk space to save:
cat << EOF > /etc/security/audit_control
dir:/var/audit
dist:off
flags:lo,aa
minfree:20
naflags:lo,aa,ex
policy:cnt,argv
filesz:2M
expire-after:10M
EOF
# Start service to test.
service auditd start
# View audit log:
praudit /var/audit/current
# Track live:
praudit /dev/auditpipe
# }
# Version control /etc & /usr/local/etc {
# Unfortunately etckeeper has no freebsd support, so a manual git repo is what is left to do.
cd /etc
touch .gitignore
git init
git add .
git commit -m "Initial commit"
cd /usr/local/etc
cat << EOF > .gitignore
asciidoc/
fonts/conf.avail/
EOF
git init
git add .
git commit -m "Initial commit"
# }
# Python {
# Set default python version
echo >> /etc/make.conf
DEFAULT_VERSIONS=python=3.6 python2=2.7 python3=3.6
EOF
# pip is not included in python ports.
python3.4 -m ensurepip
pip3 install --upgrade pip
# NOTE at a later point pip3 broke and I did
portmaster devel/py-pip
pip3 install --upgrade pip
# }
# Anti-virus with clamAV {
# Reference: http://www.octopuscs.com/blogs/Windows/How-to-install-clamav-on-FreeBSD
portmaster security/clamav
# Note that the rc.conf.d scipts has _ instead of - that the rc.d script has in the name. It seems to be that the 'name' variable in the rc.d script mandates what the rc.conf.d file should be called.
cat << EOF > /usr/local/etc/rc.conf.d/clamav_clamd
clamav_clamd_enable="YES"
EOF
cat << EOF > /usr/local/etc/rc.conf.d/clamav_freshclam
clamav_freshclam_enable="YES"
EOF
cat << EOF > /usr/local/etc/clamd.conf
### Own Configuration below ###
# Skip scanning emails, like "Heuristics.Phishing.Email.SpoofedDomain". My /home/erikw/.mail/spam/ files gets triggered, and I know they are bad already.
PhishingScanURLs no
EOF
# Make initial scan
freshclam
clamscan -r -i /
# Move files to quarantine
mkdir /var/local/clamscan-quarantine
chown clamav:clamav /var/local/clamscan-quarantine/
# Schedle a cronjob
cat << EOF > /etc/cron.d/clanscan
SHELL=/bin/sh
PATH=/etc:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
# Order of crontab fields
# minute hour mday month wday command
# Reference: https://www.freebsd.org/doc/handbook/configtuning-cron.html
# Reference: crontab(5).
@weekly root cron_mail -s "Weekly virus scan" "clamscan --recursive --infected --move=/var/local/clamscan-quarantine / 2>/dev/null"
EOF
# }
# Printer Brother DCP-7070DW {
# CUPS {
# Reference: https://www.freebsd.org/doc/en_US.ISO8859-1/articles/cups/printing-cups-install.html
portmaster print/cups
# This package is needed to actaully print. Used to be a part of the core package.
portmaster print/cups-filters
cat << EOF > /usr/local/etc/rc.conf.d/cupsd
cupsd_enable="YES"
EOF
service cupsd start
# Open ports in firwall for configuring from another computer in the local network.
cat << EOF >> /etc/rc.conf.d/ipfw
# cupsd web configuration interface.
firewall_myservices="${firewall_myservices} 631/tcp"
EOF
service ipfw restart
# Config must be updated to allow connection from other computer. This will rewrite the cups conf and restart the daemon.
cupsctl --remote-admin --remote-any --share-printers
cat << EOF >> /usr/local/etc/cups/cupsd.conf
# Allow connection using alias domain name, https://srv:631
ServerAlias *
EOF
# Avoid using root account for administration.
pw group add printadmin
pw groupmod printadmin -M erikw
pw group show printadmin
patch << EOF
--- /etc/cups/cups-files.conf
- SystemGroup wheel
+ SystemGroup wheel printadmin
EOF
service cupsd restart
# Install drivers, if generic ones does not do it.
# Reference: http://tdotc.eu/2007/06/02/using-the-brother-printer-drivers-with-freebsd/
portmaster port emulators/linux_base-c7
portmaster print/psutils
# Reference: https://www.freebsd.org/doc/handbook/linuxemu-lbc-install.html
kldload linux
kldstat
cat << EOF >/etc/rc.conf.d/abi
# Load linux emulation kernel module
linux_enable="YES"
EOF
sysctl -w compat.linux.osrelease=2.6.9
sysctl compat.linux.osrelease
cat << EOF >>/etc/sysctl.conf
# Set Linux kernel version to emulate. Needed for using my Brother printer drivers.
compat.linux.osrelease=2.6.9
EOF
# Hack to get printing to work.
# Puttings these commands direclty in /etc/rc.conf is not good, as this file is sourced many times during boot.
cat << EOF >> /usr/local/etc/rc.d/reload_linux_kmod
#!/bin/sh
# $FreeBSD: head/deskutils/taskd/files/taskd.in 454856 2017-11-24 23:17:50Z dbaio $
#
# PROVIDE: reload_linux_kmod
# REQUIRE: LOGIN
# KEYWORD: shutdown
. /etc/rc.subr
name=reload_linux_kmod
rcvar=reload_linux_kmod_enable
load_rc_config $name
: ${reload_linux_kmod_enable="NO"}
command=/usr/local/bin/${name}
command_args=""
run_rc_command "$1"
EOF
cat << EOF >> /usr/local/etc/rc.conf.d/reload_linux_kmod
reload_linux_kmod_enable="YES"
EOF
cat << EOF >> /usr/local/bin/reload_linux_kmod
#!/usr/bin/env sh
# HACK
# For some reason, the printing only works if we after boot unload both linux and linux64 module, then load linux module.
# Modules are first loaded from /etc/rc.conf.d/abi.
{
sleep 60
kldstat | grep -q linux64.ko && kldunload linux64
kldstat | grep -q linux.ko && kldunload linux
kldload linux || :
} &
EOF
# By trail-and-error it was found that hostname resolver in the linux emulation was blocking the printing from working.
# Reference: https://www.freebsd.org/doc/handbook/linuxemu-lbc-install.html
# NOTE this was not true, the issue was to reload the linux kernel.
cat << EOF >> /compat/linux/etc/host.conf
order hosts, bind
multi on
EOF
su - erikw
# Fetch LRP & Cups package. Install Cups before LPR.
mkdir ~/src/brother_dcp-7070dw
cd ~/src/brother_dcp-7070dw
mkdir lpr && cd lpr
curl -O -J http://www.brother.com/pub/bsc/linux/dlf/cupswrapperDCP7070DW-2.0.4-2.i386.rpm
tar xvjf *.rpm
sudo cp -r usr/local/Brother /usr/local
sudo cp -r var/spool/lpd/DCP7070DW /var/spool/lpd
cd ..
mkdir cupswrapper && cd cupswrapper
curl -O -J http://www.brother.com/pub/bsc/linux/dlf/dcp7070dwlpr-2.1.0-1.i386.rpm
tar xvjf *.rpm
sudo cp -r usr/local/Brother/Printer/DCP7070DW/cupswrapper /usr/local/Brother/Printer/DCP7070DW
sed -i '' \
-e 's$/etc/init.d/cups$/usr/local/etc/rc.d/cupsd$g' \
-e 's$/etc/init.d$/usr/local/etc/rc.d$g' \
-e 's$/usr/share$/usr/local/share$g' \
-e 's$/usr/lib$/usr/local/lib$g' \
-e 's$/usr/lib64$/usr/local/lib64$g' \
-e 's$/usr/bin$/usr/local/bin$g' \
usr/local/Brother/Printer/DCP7070DW/cupswrapper/cupswrapperDCP7070DW-*
exit # to root sh.
# Run config
/usr/local/Brother/Printer/DCP7070DW/cupswrapper/cupswrapperDCP7070DW-* -i
ln -s /usr/local/lib/cups/filter/brlpdwrapperDCP7070DW /usr/local/libexec/cups/filter/brlpdwrapperDCP7070DW
# In the error log, this is printed:
# "Unable to communicate with avahi-daemon: Daemon not running"
# which suggests to install avahi daemon: http://www.alexforencich.com/wiki/en/freebsd/installing_avahi
# NOTE this was not needed in the end; skip!
portmaster net/avahi
portmaster dns/nss_mdns
cat << EOF >/usr/local/etc/rc.conf.d/avahi_daemon
avahi_daemon_enable="YES"
EOF
cat << EOF >/usr/local/etc/rc.conf.d/dbus
dbus_enable="YES"
EOF
patch << EOF
--- /etc/nsswitch.conf
- hosts: files dns
+ hosts: files dns mdns
EOF
# Now visit https://srv:631/ from another computer.
# Administration > Add Printer > LPD/LPR Host or Printer > connection: socket://10.0.0.6:9100 >
# * Set:
# - Name: dcp7070dw
# - Description: Brother DCP7070-DW
# - Location: Berlin
# - Share this printer: yes
# * Chose:
# - Driver: Generic
# - Model: Generic PCL Laser Printer
# * Set printer default optons:
# - Media Size: A4
# - Duplex: DuplexNoTumble
# - Toner Saver: On
# Set default printer.
lpstat -p -d
lpoptions -d dcp7070dw
# Test it!
echo "test" | lpr
lpq
# Look for errors here
tail -f /var/log/cups/error_log
# }
# Google Cloudprint {
# Documentation: https://github.com/armooo/cloudprint
# NOTE Google Cloudprint was suspended 2020
portmaster print/cloudprint
cloudprint -i dcp7070dw
cat << EOF >/usr/local/etc/rc.conf.d/cloudprint
cloudprint_enable="YES"
cloudprint_flags="-i dcp7070dw"
EOF
service start cloudprint
# If getting authentication problems after not running for a while, log out and re-register
cloudprint -l
# Manage printers at https://www.google.com/cloudprint#printers
# Android: Settings > Advanced > Printing > Cloud Print > triple dots > Settings > Manage printers
# Possible to share to other Google users.
# }
# }
# Wake on LAN (WoL) {
# Reference: https://wiki.archlinux.org/index.php/Wake-on-LAN
# Reference: http://linux-bsd-sharing.blogspot.com/2012/06/howto-enable-wake-on-lan-on-freebsd.html
# WoL does not work on WiFi card, only physical Eth.
# First make sure that my card supports WOL
# List all drivers that have WOl support
grep -l IFCAP_WOL /usr/src/sys/dev/*/*.c
# Now compare this against my NICS, which of these have the WOL_MAGIC option/capability?
ifconfig -m
# Collect the MAC address of the card that supports it.
ifconfig -m | grep ether
# Now, try it from arch:
# laptop$ yaourt -S wol
# laptop$ sudo wol -i 10.0.0.2 ...
# laptop$ sudo wol -i 255.255.255.255 ....
# From macOS:
# Reference: https://apple.stackexchange.com/questions/95246/wake-other-computers-from-mac-osx
# mac$ brew install wakeonlan
# mac$ wakeonlan -i 10.255.255.255 ....
# From Android:
# * https://play.google.com/store/apps/details?id=co.uk.mrwebb.wakeonlan
# * https://play.google.com/store/apps/details?id=com.bitklog.wolon
# To wake up from remote, set up in router forwarding rule for UDP port 7 & 9 to server.
# }
# Move /boot to USB stick {
# Reference: https://web.archive.org/web/20180218101816/https://vesterman.com/FreeBSD/FullDiskEncryption
# Insert USB stick. Shows up as /dev/da0 in this case.
# Clear old partitions
gpart destroy -F da0
# Create a GPT partitioning scheme on the USB drive:
gpart create -s gpt da0
# Add two partitions to the USB drive, the first for the boot loader and the second for /boot:
gpart add -t freebsd-boot -s 512k -a 4k da0
gpart add -t freebsd-ufs -l boot -s 1g -a 1m da0
gpart show da0
# Install the bootcode to partition 1 on the USB drive:
gpart bootcode -b /boot/pmbr -p /boot/gptboot -i 1 da0
# Create File System
newfs -U -L bootstick_straps /dev/da0p2
# Copy existing boot stuff to USB stick
mkdir /media/usb_media
mount /dev/da0p2 /media/usb_media
cp -Rpv /bootpool/ /media/usb_media/
# Now reboot and select the USB drive in BIOS/UEFI
# Automatically mount the disk
# Reference: https://people.freebsd.org/~trhodes/doc/handbook/geom-glabel.html
# If label was forgot with newfs, add it aftwards:
gpart modify -i 1 -l bootstick_code da0
gpart modify -i 2 -l bootstick_straps da0
mkdir /media/bootstick_straps
cat << EOF >> /etc/fstab
/dev/gpt/bootstick_straps /media/bootstick_straps ufs rw,late 0 0
EOF
mount -al
# Remove encryption key on /bootpool
rm /bootpool/boot/encryption.key
# Now, always update the USB stick code with updates from /bootpool whenever those are updated from system upgrades.
# NOTE that /bootpool does not have the encryption key anymore, only the USB stick!!
cat << EOF >> /root/.profile
alias bootfiles_copy_to_usbstick='cp -Rpv /bootpool/ /media/bootstick_straps/'
EOF
# Now reboot again and verify
# 1) that the usb stick is mounted
# 2) system is not loaded if usb stick is not plugged in
# Now update BIOS/UEFI so that USB drivers are highest in the boot order prio.
# NOTE I was never able to create an USB stick that my NUC would find during the boot sequence. It's possible to select it manually in the F10 boot mentu, but it was never detected automatically. I tried 4 different sticks from different brands. So I reverted chagned above: added back encryption.key to system disk and commented out alias, and fstab entry.
# }
# Python setup {
# Firt make sure that meta package is not installed
pkg delete python
# Set default version
cat << EOF > /etc/makeconf
DEFAULT_VERSIONS=python=3.7
EOF
# Install meta package
portmaster lang/python
# Upgrade to newer version, see /usr/port/UPDATING for latest instructions, here's a copy of py37
# For portmaster users:
portmaster -o lang/python37 python36
REINSTALL="$(pkg info -o py36-\* | awk '{printf "%s ", $2}')"
pkg delete -f py36-\*
portmaster $REINSTALL
REBUILD=$(pkg query -g "%n:%dn" '*' | grep py3 | grep -v py37 | cut -d : -f 1 | sort -u)
portmaster $REBUILD
REBUILD2=$(pkg list | grep python-36 | xargs pkg which | awk '{print $6}' | sort -u)
portmaster $REBUILD2
# Additionally I had to rebuild vim myself:
portmaster editors/vim
# }
# }
# System Upgrades & Package Management {
# TL;DR {
freebsd-version
freebsd-update fetch
znp freebsd-update install
znp freebsd-update upgrade -r 11.2-RELEASE # Upgrade to newer release branch.
pkg update
pkg version -vl '<'
znp pkg upgrade
portsnap auto
portmaster -L
less /usr/ports/UPDATING
znp portmaster -aGyd --no-confirm
# }
# FreeBSD source {
# For some tasks, like reading kernel module documentation, the base FreeBSD source must be obtained to /usr/src
# Reference: https://www.freebsd.org/doc/handbook/svn.html
# Get certificates to verify the svn connection:
pkg install ca_root_nss
# Check out the base
svnlite checkout https://svn.FreeBSD.org/base/head /usr/src
# But let's switch to our branch
freebsd-version
svnlite ls https://svn.FreeBSD.org/base/
svnlite ls https://svn.FreeBSD.org/base/releng/
svnlite switch https://svn.FreeBSD.org/base/releng/11.1 /usr/src
# See current branch
svnlite info /usr/src
# Check out the docs
svnlite checkout https://svn.FreeBSD.org/doc/release/11.1.0 /usr/doc
# Update docs:
cd /usr/doc
svnlite up
# Or simply
svnlite up /usr/doc
# }
# Upgrade FreeBSD base system {
## Patch upgrades {
# Reference: https://www.freebsd.org/doc/handbook/updating-upgrading-freebsdupdate.html
# A full upgrade of security patches typically consists of
freebsd-update fetch
freebsd-update install
pkg upgrade
# A reboot can be needed after $(freebsd-update install), for kernel changes and upgraded programs to work.
# If there was problem, then
freebsd-update rollback
# Enable daily check for updates. Email will be sent when updates were fetched.
cat << EOF > /etc/cron.d/freebsd-update
SHELL=/bin/sh
PATH=/etc:/bin:/sbin:/usr/bin:/usr/sbin
# Order of crontab fields
# minute hour mday month wday command
# Reference: https://www.freebsd.org/doc/handbook/configtuning-cron.html
# Reference: crontab(5).
# Fetch FreeBSD base system updates, and send email if found.
@daily root freebsd-update cron
EOF
## }
## Major & Minor upgrades {
### Preperations {
# First, read the release notes for the new version: https://www.freebsd.org/releases/
# # Make sure that latest patch levels are installed with freebsd-update, and all latest packages with pkg(1) and portmaster are installed.
# For major version upgrades, consider using beadm to create a complete bootable copy of the old system. Seems like beadm(1) is being replaced with bectl(8).
# Reference: https://www.adminbyaccident.com/freebsd/how-to-update-freebsd-using-beadm/
# Reference: https://www.freebsd.org/cgi/man.cgi?query=beadm
# Reference: https://blather.michaelwlucas.com/archives/2363
bectl list
# Create snapshot of current
bectl create default@yyyy-mm-dd_pre_freebsd_xx.z_upgrade
zfs list -t snapshot | grep pre_freebsd
# Create new environment to install upgrade to
bectl create 12.0-RELEASE
bectl activate 12.0-RELEASE
reboot
freebsd-update install
# Optionally make a backup of /etc in case of problem with mergemaster. OR make a zfs snapshot before.
###}
### Upgrade {
# Reference: https://www.freebsd.org/doc/handbook/updating-upgrading-freebsdupdate.html#freebsdupdate-upgrade
# Check in all unstaged changes in /etc /usr/local/etc git repos
cd /etc; git status
cd /usr/local/etc; git status
# Clean up packages that are not needed before upgrade
znp pkg autoremove
# Create pre-backup snapshot of the whole system
zfs snapshot -r zroot@12.0-RELEASE_upgrade_pre
zfs list -t snapshot
freebsd-version
freebsd-update -r 12.0-RELEASE upgrade # Latest release version can be found at https://www.freebsd.org/releases/
freebsd-update install
shutdown -r now
freebsd-update install # Continues with clean-up phase.
freebsd-version
# During upgrade, there might be a lot of configuration conflicts. It can help to look at the complete whole new files:
# First revert local changes not in remote branch.
svn revert --recursive .
# Default to accept the branch versions of a file in conflict. See $(svnlite help switch).
svnlite switch --accept tf https://svn.FreeBSD.org/base/releng/12.0 /usr/src
# Check in all unstaged changes in /etc /usr/local/etc git repos
cd /etc; git status; git add .; git commmit -m "Upgrade to 12.0-RELEASE"
# After upgrading a Major FreeBSD version, then the ABI has changes so we must reinstall all binaries:
pkg-static upgrade -f
portsnap auto
# Check if there are blocking vulnerabilities that we need to ignore with "-m DISABLE_VULNERABILITIES=yes" to portmaster
pkg audit -F
# Upgrade to 12.1: package net/samba410 could not build because conflicting python package versions. Solution, uninstall the package, $(pkg autoremove), then do the re-build of all other packages, then install samba410 (which works, problem was only during full rebuild).
portmaster -af -Gyd
# Check config files again
cd /etc; git status
cd /usr/local/etc; git status
# End by a last update command, to finish of loose ends:
# Upgrade to 12.1: gave "Cannot identify running kernel" here. Solution was to $(ln -s /bootpool/boot /boot) as freebsd-update gets current versin from the file $(sysctl -n kern.bootfile). Reference: https://forums.freebsd.org/threads/cannot-identify-running-kernel.43329/
freebsd-update install
# Clean up
znp pkg autoremove
# fetch newer versions of packages
portsnap auto
cd /usr/ports
make index
znp portmaster -aGyd
# Check config files again
cd /etc; git status
cd /usr/local/etc; git status
# Create post-backup snapshot of the whole system
zfs snapshot -r zroot@12.0-RELEASE_upgrade_post
zfs list -t snapshot
# Compare the system against how it's expected to look.
freebsd-update IDS >> /tmp/outfile.ids
# View all files that differ from the system with the release:
cat outfile.ids | awk '{ print $1 }' | more
# And fix expected permissions e.g. like
grep "have 0644" /tmp/outfile.ids | awk '{print $1}' | xargs echo chmod 0644:
# Reboot and check system log for errors
echo >/var/log/messags
reboot
less /var/log/messages
# Check service that they work
# - Samba
# - web server (from external network)
# - openvpn
# - port knocking + ssh
# - daily emails about scheduled jobs
# Now fetch patch version of the OS
freebsd-update fetch
freebsd-update install
###}
## }
# }
# pkg - install binary packages {
pkg update
# List installed packages:
pkg info
pkg info vim
# To see files installed by package:
$ pkg info -l vim
# To see which package installed a file:
pkg which /usr/local/sbin/lsof
# List only top-level installed, not dependencies:
pkg prime-origins
pkg search vim
pkg install vim tmux
## See freebsd_packages.txt for all packages needed
# To see pkg-message again after installing, do
pkg info -D -x taskd
# Note: mosh does not give scrollback in the terminal, thus always use screen/tmux with mosh
# Delete package
pkg delete vim
# Remove now unneeded dependencies:
pkg autoremove
# This removes all packages that does not refere to any installed packages and are registered as automatic. To see which are not set to automatic:
pkg set -A0
# List outdated packages:
pkg version -vl '<'
# The default is -P is to check against ports, however if you are _not_ interesting in using a ports version of a pkg version, then use
pkg version -R -vl '<'
# Upgrade packages
pkg upgrade
# Check for vulnerabilities, Do this from time to time.
pkg audit -F
# Remove packages which are not in the package index anymore:
# Reference: https://raw.githubusercontent.com/freebsd/freebsd-ports/master/UPDATING
pkg version -l \? | cut -f 1 -w | grep -v compat | xargs pkg delete -fy
# Enable daily audit check
# Reference: https://www.freebsd.org/doc/handbook/security-pkg.html
cat << EOF >> /etc/periodic.conf
# Enable dialiy $(pkg audit) run
# old: daily_status_security_pkgaudit_enable="YES"
security_status_pkgaudit_enable="YES"
EOF
# }
# ports(7) - install from source {
# To findout location of a port:
whereis vim
# or using the port search
cd /usr/ports
make fetchindex
make search name=vim
# or the quicksearch for less output
make quicksearch name=vim
# Update ports tree:
portsnap fetch
portsnap update
# Or simply all in once:
portsnap fetch update
# or better
portsnap auto
# Install packages
cd /usr/ports/textproc/p5-ack
# Only fetch distfile to /usr/ports/distfiles/
make fetch
# Set configuration options
make showconfig
make config
# Or just/finally install and clean up used space afterwards
make install clean
# Install in to other prefix
make PREFIX=/home/erikw/bin/ install
# See list of installed packages in freebsd_packages.txt
# To remove, remove with pkg
pkg remove p5-ack
# or use the ports makefile target
cd /usr/ports/textprox/p5-ack
make deinstall
# portmaster {
# Manage port updates with portmaster. Seems to be favrouted to portugprade, and don't depend on ruby.
# https://www.freebsd.org/doc/handbook/ports-using.html#portmaster
cd /usr/ports/ports-mgmt/portmaster
make install clean
# Enable logging for portmaster.
cat << EOF >> /usr/local/etc/portaster.rc
PM_LOG=/var/log/portmaster.log
EOF
# NOTE always read the file /usr/ports/UPDATING before updating!
# List ports per cateogy and look for updates
portsnap auto # Update /usr/ports itself
portmaster -L
# Upgrade everything
portmaster -a
# Upgrade everything, and skip $(make config)
portmaster -aG
# Or do that with a dry run
portmaster -an
# Exclude (broken) port from upgrade
portmaster -aG -x brokenport
# However this will use a ports version if this is newer than the installed version from pkg(1). Use only packages:
# Will this still update packages that was not available in pkg but only as port?
# It seems to be not advices to mix binary packages and ports, so maye I should let $(portmaster -a) take over and upgrade the binary installed packages?
portmaster -PP
# Upgrade only one port:
portmaster textprox/p5-ack
# Ingore conflicting depdendencies e.g. different python versions of the same package
portmaster -m -DDISABLE_CONFLICTS print/cloudprint # Conflict on py27-docutils vs py36-docutils
# Clean out dependencies that are no longer being dependent on.
portmaster -s -d
# To ignore known security vulnerabilities thst block a system upgrade (consider wisely!):
portmaster -m DISABLE_VULNERABILITIES=yes ...
# }
# }
# Port upgrade emails {
# Set up autoatic emails about available updates.
cat << EOF > /etc/cron.d/ports-upgrades
SHELL=/bin/sh
PATH=/etc:/bin:/sbin:/usr/bin:/usr/sbin
# Order of crontab fields
# minute hour mday month wday command
# Reference: https://www.freebsd.org/doc/handbook/configtuning-cron.html
# Reference: crontab(5).
@daily root : Upgradable Ports ; pkg update >/dev/null && portsnap auto >/dev/null && pkg version -vl '<'
EOF
# }
#}
# Service setup {
# Email with ssmtp {
# To send an email, do this. Note, gmail puts these in the Spam mailbox.
echo "hej" | mail -v -s "test" user@gmail.com # NOTE seems like ssmtp/loopia does not accept sending outside own domain => send to "root@erikw.me" or "root".
# However, sending to root@erikw.me works fine.
echo "hej" | mail -v -s "test root2" root@erikw.me
# Tip; trigger periodic emails manually by running periodic like
periodic daily
# NOTE msmtp is supposedly the more modern version of ssmtp. However ssmtp seems to work, so let's upgrade when it's not working.
# Reference: https://www.freebsd.org/doc/handbook/outgoing-only.html
# portsnap mail/ssmtp - NOPE then we miss the replace option that fixes /etc/mail/mailer.conf
cd /usr/ports/mail/ssmtp
make install replace clean
# Disable sendmail.
# Reference: https://www.freebsd.org/doc/handbook/mail-changingmta.html#mail-disable-sendmail
cat << EOF > /etc/rc.conf.d/sendmail
sendmail_enable="NO"
sendmail_submit_enable="NO"
sendmail_outbound_enable="NO"
sendmail_msp_queue_enable="NO"
EOF
cat << EOF >> /etc/periodic.conf
# Disable sendmail(8) specific tasks, as it's replaced by ssmtp.
daily_clean_hoststat_enable="NO"
daily_status_mail_rejects_enable="NO"
daily_status_include_submit_mailq="NO"
daily_submit_queuerun="NO"
EOF
service sendmail stop
# Config ssmtp:
cat << EOF > /usr/local/etc/ssmtp/ssmtp.conf
root=root@erikw.me
mailhub=mail.erikw.me
rewriteDomain=erikw.me
hostname=_HOSTNAME_
UseTLS=YES
UseSTARTTLS=Yes
EOF
# To map local user to email address for ssmtp, edit /etc/mail.rc. (for other MTAs /etc/aliases is used)
# Reference: http://possiblelossofprecision.net/?p=591
cat << EOF >> /etc/mail.rc
alias root root@erikw.me
alias erikw erikw@erikw.me
EOF
# Seems ike revaliases could be needed for emails to root to be mapped to right email address, by ddclient?
# NOTE seems like mailcluster.loopia.se can only Rsrv to addreeses that have set up mail forward aliases set up in their webinterface.
# If they are not added: "Recipient address rejected: User unknown in relay recipient table"
# Set up Loopia aliases for {root,admin,erik,erikw,contact}@erikw.me -alias forward to-> user@gmail.com
cat << EOF > /etc/usr/local/ssmtp
root:root@erikw.me:mail.erikw.me
EOF
# But to make other programs work, like default configuratin for ddclient that sends email to the local root users mailbox, also
cat << EOF >> /etc/aliases
# Forward local user root's email to my web host's email server, via ssmtp.
root: root@erikw.me
EOF
# Now try
service ssmtp start
echo "hej" | mail -v -s "test ssmtp to root" root
echo "hej" | mail -v -s "test ssmtp to root@erikw.me" root@erikw.me
echo "hej" | mail -v -s "test ssmtp to erikw" erikw
# Trace sent mail with
tail -f /var/log/maillog
# enable further debugging in /usr/local/etc/ssmtp/ssmtp.conf with Debug=YES
# Finally reboot for changes to really take effect.
# The FreeBSD system cron is using sendmail, and changing seems not possible without recompiling it (no port available). Installing another cron seems cumbersome.
# Solution: use my wrapper /usr/local/sbin/cron_mail around all commands executed in cron.
# }
# restic automatic backup {
# Install restic:
portsnap auto
cd /usr/ports/sysutils/restic
make install clean
# Install bash, needed for my restic_backup.sh script.
pkg update
pkg install bash
# Also, make bash default root shell.
chsh -s /usr/local/bin/bash
# Enable clear-screen shortcut
cat << EOF > ~/.inputrc
Control-L: clear-screen
set keymap vi-command
Control-L: clear-screen
# Ignore case in completion
set completion-ignore-case On
EOF
# FUSE is needed for restic-mount:
cat << EOF >> /boot/loader.conf
# FUSE kernel module is needed for restic $(kldload fuse)
fuse_load="YES"
EOF
# Instead of the systemd service and timer, set up with cron
# NOTE could use chronic to only get email when it fails, but I like to see how much was backed up. http://habilis.net/cronic/
cat << EOF > /etc/cron.d/restic
SHELL=/bin/sh
PATH=/etc:/bin:/sbin:/usr/bin:/usr/sbin
# Order of crontab fields
# minute hour mday month wday command
# Reference: https://www.freebsd.org/doc/handbook/configtuning-cron.html
# Reference: crontab(5).
@midnight root /usr/local/sbin/restic_backup.sh
@monthly root /usr/local/sbin/restic_check.sh
EOF
# Email seems to be sent automatically to root@erikw.me. Envvar MAILTO could also be set in the crontab file.
# }
# package dump {
# Log installed packes by using pkg-query:
cat << EOF >/usr/local/sbin/dump_installed_packages.sh
#!/usr/bin/env sh
log_dir=/var/local/log/packages_dump
date=$(date "+%Y-%m-%d-%H%M%S")
log_file_base="${log_dir}/${date}"
test -d $log_dir || mkdir -p $log_dir
# all packages
pkg query "%a %R %v %o %n %c" | sort > "${log_file_base}_all.txt"
# pkg packages
pkg query "%a %R %o %n" | grep "^0" | grep FreeBSD | cut -d' ' -f3 | sort > "${log_file_base}_pkg.txt"
# ports packages
pkg query "%a %R %o %n" | grep "^0" | grep -v FreeBSD | cut -d' ' -f3 | sort > "${log_file_base}_ports.txt"
EOF
# Schedule this to be run every day.
cat << EOF > /etc/cron.d/dump_packages
SHELL=/bin/sh
PATH=/etc:/bin:/sbin:/usr/bin:/usr/sbin
# Order of crontab fields
# minute hour mday month wday command
# Reference: https://www.freebsd.org/doc/handbook/configtuning-cron.html
# Reference: crontab(5).
@daily root /usr/local/sbin/dump_installed_packages.sh
EOF
# }
# Samba network share {
# I skipped sharing my cups printer, as it's already discoverable on the network itself. https://wiki.archlinux.org/index.php/CUPS/Printer_sharing#Sharing_via_Samba
portmaster net/samba48
# Start daemons
cat << EOF > /usr/local/etc/rc.conf.d/samba_server
samba_server_enable="YES"
nmbd_enable="NO"
samba_enable="NO"
EOF
# Create user for the share with these settings:
#Username : pcguest
#Password : <blank>
#Full Name :
#Uid : 1002
#Class :
#Groups : pcguest
#Home : /home/pcguest
#Home Mode :
#Shell : /usr/sbin/nologin
#Locked : no
adduser
pdbedit -a -u pcguest # No password.
# Create datset with refquota
# Source: https://docs.oracle.com/cd/E23823_01/html/819-5461/gazvb.html
zfs create -o mountpoint=/var/samba zroot/samba
zfs set refquota=100g zroot/samba
zfs list zroot/samba
# Config a public share.
mkdir /var/samba/pub
chmod 755 /var/samba/pub
chown -R pcguest:pcguest /var/samba/pub
cat << EOF > /usr/local/etc/smb4.conf
# See smb.conf(5)
[global]
workgroup = WORKGROUP
server string = Samba Server %v
netbios name = server-name
security = user
map to guest = Bad User
dns proxy = no
guest account = pcguest
# Make this server show up in Windows' network discovery.
# Reference: https://ubuntuforums.org/showthread.php?t=1891378
# Reference: https://askubuntu.com/questions/661611/make-samba-share-visible-in-windows-network
wins support = yes
local master = yes
preferred master = yes
name resolve order = bcast host
# Non-working attempts to t achieve password-less logon in Windows 10.
# Setting this to yes allows ntlmv1, which allows for entering public shares without having to enter something bogus in the login dialog.
# NOTE does not seem to work
#ntlm auth = yes
# Reference: https://serverfault.com/questions/211128/can-samba-security-user-be-used-for-guest-share-without-windows-login-prompt
# Not working
#username map = /etc/samba/smbusers
[homes]
comment = Home Directories
browseable = yes
writable = yes
readonly = no
create mask = 0755
directory mask = 0755
[pub]
comment = Public files
path = /var/samba/pub/
public = yes
browsable = yes
read only = no
writable = yes
create mask = 0644
directory mask = 0755
force user = pcguest
force group = pcguest
EOF
# Make a symlink. Some programs, like webmin, expects the config to be at this path.
ln -s /usr/local/etc/smb4.conf /usr/local/etc/smb.conf
# Open ports in firewall.
# Reference: https://forums.freebsd.org/threads/what-are-correct-ipfw-settings-for-samba.19675/
cat << EOF >> /etc/rc.conf.d/ipfw
# Open samba services
#firewall_myservices="${firewall_myservices} hosts2-ns/tcp netbios-ns/tcp netbios-dgm/tcp netbios-ssn/tcp microsoft-ds/tcp"
# These names does not work for some reason, so let's use port numbers instead.
firewall_myservices="${firewall_myservices} 81 137 138 139 445"
EOF
# Enable home folder for ~erikw to be mounted.
pdbedit -a -u erikw #
# Test!
# NOTE After adding server-name as network local DNS server, and possibly after setting up DHCP server, it seems like \\server-name name is tried to be resolved as a DNS name instead of samba (WINS?) name. Thus the FQDN is needed \\server-name. or \\srv.
service samba_server start
# From another Linux computer, scan for samba hosts:
smbtree -N
# browse what shares are available by
smbclient -L server-name -U%
# Then connect to a share like
smbclient -N -W WORKGROUP '\\server-name\pub'
# Or mount it as a filesystem
mount -t cifs //server-name/pub /mnt/server-name_pub/ -o password=whatever,workgroup=workgroup
# Create a README for legal reasons:
cat << EOF > /var/samba/README.bak
Hello,
these is a public share on this network, served by server-name. You can put your files here temprarily, but do not expect them to persists as everyone has write access here.
The server owner take no responsibility for the content put here - you are completely responsibly yourself for all files you put here.
EOF
cp /var/samba/README.bak /var/samba/pub/README
# Set stickbit so that ownly the owner of the file can remove it. This seems to prevent deletion from some smb clients, but not all.
chmod +t /var/samba/pub
chmod 444 /var/samba/pub/README
chown root:wheel /var/samba/pub/README
# Make local user ~erikw able to create files in share
# Reboot required to group change to take effect.
pw groupmod pcguest -M erikw
pw group show pcguest
# Windows notes.
# To list connected smb shares in windows:
net use
# To disconnect to use, use
net use \\server-name\pub /delete
# List computers on network
net view
# List shares
net view \\server-name
# Mount a share
net use x: \\server-name\pub
# Tell windows to always use blank password and username for share
net use \\server-name\pub "" /user:""
# }
# FTP server {
# Reference: https://www.freebsd.org/doc/handbook/network-ftp.html
# Disallow pcugest to do FTP.
echo pcguest >> /etc/ftpusers
# Set greeting and motd
echo "This is the FTP service by Server, authenticate and behave." >> /etc/ftpwelcome
echo "All actions are logged. You are complete responsibly yourself for all files you upload - we take no legal responsibilities." > /etc/ftpmotd
# Enable & start the service
cat << EOF > /etc/rc.conf.d/ftpd
ftpd_enable="YES"
EOF
service ftpd start
# Try the connection
ftp erikw@localhost
# Enable FTP in the firewall.
# Active
cat << EOF >> /etc/rc.conf.d/ipfw
# FTP - Active mode
# ftpd: this enabled active mode, where server opens the data channel to the client. Use this so we don't have to open incomming trafic on the high level ports for passive. mode.
# Reference: https://stackoverflow.com/questions/1699145/what-is-the-difference-between-active-and-passive-ftp
# Reference: https://forums.freebsd.org/threads/ftp-ipfw-passive-rules.34618/
firewall_myservices="${firewall_myservices} ftp"
EOF
service ipfw restart
# Passive
cat << EOF >> /etc/ipfw.rules
# FTP - Passive mode
# Reference: https://forums.freebsd.org/threads/ftp-ipfw-passive-rules.34618/
# Disabled! because I don't want to expose these ports. Using another FTP server like pure-ftpd would allow to define what range to use.
#$cmd 120 allow all from any 1024-65535 to any 1024-65535 in setup keep-state
EOF
# Don't serve public FTP - dangerous!
# But create a new user for an authenticated FTP
# Note - some client will requuire to enter a username, use "ftp" or "anonymous"
useradd
#Username : ftp
#Password : <blank>
#Full Name :
#Uid : 1003
#Class :
#Groups : ftp
#Home : /home/ftp
#Home Mode :
#Shell : /usr/sbin/nologin
#Locked : no
echo "Here may be public files." > /home/ftp/README
chgrp wheel /home/ftp/README
chmod 444 /home/ftp/README
# Prevent creation of file in this directory.
# See ftpd(8)
chmod 555 /home/ftp
chgrp wheel /home/ftp
# Also create another jailed ftp user that I can use to upload files to myself (feels securer than using my real user ~erikw).
adduser
#Username : ftp.dump
#Password : *****
#Full Name :
#Uid : 1004
#Class :
#Groups : ftp.dump
#Home : /home/ftp.dump
#Home Mode :
#Shell : /usr/sbin/nologin
#Locked : no
# Chroot the user to only see the home directory
echo ftp.dump >> /etc/ftpchroot
cat << EOF > /etc/shells
# ftpd(8) requres a valid login shell to be set for the user, but I don't want to allow login for the ftp user
# Making nologin a valid shell works around this.
/usr/sbin/nologin
EOF
# WARNING FTP is is plain text, so someone could pick up the password and start uploading shit here. Don't use this user uneless needed. Prefer scp!
# Thus, disable for now:
echo ftp.dump >>/etc/ftpusers
# For the same reason, disallow ~erikw:
echo erikw >>/etc/ftpusers
# Since I’m not activly using this, and if I would, I would not use the anonymous passwordless user ftp. Thus remove it for now as it only exposes security risk:
rmuser ftp
# Update /usr/local/etc/rkhunter.conf and remove it form PASSWORDLESS_ACCOUNTS variable.
# }
# Unbound DNS resolver/cache {
# First, make sure that server-name is configured to a static IP in the network, here 192.168.178.55.
cat << EOF > /usr/local/etc/unbound/unbound.conf
# See unbound.conf(5)
server:
# Server
# Where to log. Logfile is relative to the chroot or directory set.
# For FreeBSD's ports unbound; this is /usr/local/etc/unbound.
logfile: "unbound.log"
# Level of verbosity to log with.
verbosity: 1
# Log validation errors.
val-log-level: 2
# Connection
# Listen on all interfaces, answer queries from the local subnet.
interface: 0.0.0.0
interface: ::0
access-control: 192.168.178.0/24 allow
# Get network part of IPv6 with ifconfig + https://networklessons.com/ipv6/how-to-find-ipv6-prefix/
access-control: 2003:8c:4d00:4c00::/64 allow
# TCP needed for Enable DNS over TLS
do-tcp: yes
# Performance
# Send less data on the network.
minimal-responses: yes
# Fetch popular cache elements before they expire again.
prefetch: yes
# Lower latency on requests by fetching public DNSKEYs earlier.
prefetch-key: yes
# Speed optimization?
rrset-roundrobin: yes
# Number of threads to spin up. Set this to number of cores in computer.
# $ sysctl -a | grep -i core
num-threads: 2
# Faster UDP with multithreading (might only on Linux, but fails silently if not).
so-reuseport: yes
# Cache sizes.
# See https://www.unbound.net/documentation/howto_optimise.html
# Increase message cache size from default 4m.
msg-cache-size: 64m
# Cache slab memory allocations. Set this to number of cores in computer.
msg-cache-slabs: 2
# Increase RRSet (resource records) cache from default 4m.
# Recommendation is rrset-cache = 2 * msg-cache
rrset-cache-size: 128m
# Number slabs allocations. Set this to number of cores in computer.
rrset-cache-slabs: 2
# message vs rrset cache?
# "The message cache contains the 'message formats', with DNS rcodes and validation status (like the header part of 'dig' output). The rrset cache contains the RR data (like the data part of 'dig' output)."
# Reference: https://www.unbound.net/pipermail/unbound-users/2010-September/001360.html
# Security
# Send NXDOMAIN for subdomain of known NXDOMAIN.
harden-below-nxdomain: yes
# Send extra query to enfoce DNSSEC validation on nameserver. Degrated performance.
# harden-referral-path: yes
# No downgrate when multiple allowed algorithms.
harden-algo-downgrade: no
# Randomly change case of requested name, and verify response, to foil spoofing attempts.
# Using this experimental feature seems to be troublesome in practice.
#use-caps-for-id: yes
# Why give away information that can be used against us? Disable id.serve & hostname.bind queries.
hide-identity: yes
# Refuse version.server & version.bind queries.
hide-version: yes
# DNSSEC
# Reference: https://www.unbound.net/documentation/howto_anchor.html
# Reference: https://info.menandmice.com/blog/bid/40298/End-to-End-DNSSEC-using-Unbound-DNS
# How test it works:
# * https://dnssec.vs.uni-due.de/
# * http://conn.internet.nl/connection/
# * https://www.rootcanary.org/test.html
# * visiting http://www.rhybar.cz/ should print a log messages:
# * $(dig com. SOA +dnssec | grep ad), Authenticated Data flag should be present.
# info: validation failure <www.rhybar.cz. AAAA IN>: no keys....
# Run this to set up root.key by fetching trusted keys.
# $ unbound-anchor
auto-trust-anchor-file: "root.key"
# Local domain aliases.
# Reference: https://www.bentasker.co.uk/documentation/linux/279-unbound-adding-custom-dns-records
local-data: "srv. A 192.168.178.55"
local-data: "server-name. A 192.168.178.55"
# When using server-name as DNS server in the network, this alias is lost to my router. Let's keep it!
local-data: "fritz.box A 192.168.178.1"
# Enable remote control interface, that can be accessed e.g. with unbound-control(8).
# print statistics without resetting them
# $ unbound-control stats_noreset
# Dump cache to stdout
# $ unbound-control dump_cache
# flush cache and reload configuration
# $ unbound-control reload
# To enable this, run this command to generate server keys.
# $ unbound-control-setup
# Reference: https://wiki.archlinux.org/index.php/Unbound#Setting_up_unbound-control
remote-control:
control-enable: yes
control-interface: 127.0.0.1
#control-use-cert: no
server-key-file: "/usr/local/etc/unbound/unbound_server.key"
server-cert-file: "/usr/local/etc/unbound/unbound_server.pem"
control-key-file: "/usr/local/etc/unbound/unbound_control.key"
control-cert-file: "/usr/local/etc/unbound/unbound_control.pem"
# Forward all requests to external (to the network) resolver.
# Reference: https://wiki.archlinux.org/index.php/Unbound#Forward_all_remaining_requests
forward-zone:
name: "."
# Cloudflare's DNS servers
#forward-addr: 1.1.1.1
#forward-addr: 1.0.0.1
#forward-addr: 2606:4700:4700::1111
#forward-addr:2606:4700:4700::1001
# DNS over TLS. Requires unbound >= 1.6.6
# Reference: http://blog.thestateofme.com/2018/04/04/howto-secure-your-dns-with-a-raspberry-pi-unbound-and-cloudflare-1-1-1-1/
# Connection can be tested with kdig
# $ kdig -d @1.1.1.1 +tls-ca +tls-host=cloudflare-dns.com example.com
# Reference: https://developers.cloudflare.com/1.1.1.1/dns-over-tls/
forward-addr: 1.1.1.1@853
forward-addr: 1.0.0.1@853
forward-ssl-upstream: yes
# Google's DNS servers
#forward-addr: 8.8.8.8
#forward-addr: 8.8.4.4
#forward-addr: 2001:4860:4860::8888
#forward-addr: 2001:4860:4860::8844
EOF
unbound-checkconf
cat << EOF >> /etc/rc.conf.d/ipfw
# DNS local caching
firewall_myservices="${firewall_myservices} domain/tcp domain/udp"
EOF
service ipfw restart
# Update the generated files in /etc/unbound with
resolvconf -i
resolvconf -a em0.dhcp < /etc/resolv.conf
# Start service
cat << EOF > /usr/local/etc/rc.conf.d/unbound
unbound_enable="YES"
EOF
service unbound restart
# Verify that we listen on port 53 for ipv4 and ipv6.
sockstat | grep :53
# Test the local alias
drill srv
# From Arch Linux:
sudo nscd -K # clear dns cache
nslookup srv. "<ip-of-srv-server>"
# Generate keys for local control interface:
unbound-control-setup
# Fetch DNSSec keys
unbound-anchor
# The trusted keys must be updated from time to time
cat << EOF >/etc/cron.d/unbound-anchor
SHELL=/bin/sh
PATH=/etc:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin/:/usr/local/sbin/
# Order of crontab fields
# minute hour mday month wday command
# Reference: https://www.freebsd.org/doc/handbook/configtuning-cron.html
# Reference: crontab(5).
# Fetch trusted DNSSEC keys for unbound.
@weekly root cron_mail unbound-anchor
EOF
# NOTE getting Android to resolv non FQDN hostnames from local domanserver does not work at the moment.
# Reference: https://stackoverflow.com/a/8651252/265508
# HOWEVER after setting up isc-dhcpd with Search Domain, it started to work in Android to resolv my local A-records!
# To support DNS over TLS, the forward-ssl-upstream setting is needed, which is found in unbound >= 1.6.6. Thus we need to install unbound from ports.
portmaster dns/unbound
cp /etc/unbound/conf.d/custom.conf /usr/local/etc/unbound/unbound.conf
cat << EOF > /etc/rc.conf.d/local_unbound
local_unbound_enable="NO"
EOF
cat << EOF > /usr/local/etc/rc.conf.d/unbound
unbound_enable="YES"
EOF
# }
# Webmin {
# Reference: https://doxfer.webmin.com/Webmin/Installation#pkg_.28FreeBSD.29
portmaster sysutils/webmin
cat << EOF > /usr/local/etc/rc.conf.d/webmin
webmin_enable="YES"
EOF
# Configure webmin:
/usr/local/lib/webmin/setup.sh
# Use default settings for all, and
# ssl: yes # Reference: http://www.webmin.com/ssl.html
service webmin start
w3m https://localhost:10000
cat << EOF >> /etc/rc.conf.d/ipfw
# Webmin
firewall_myservices="${firewall_myservices} 10000/tcp"
EOF
# Make port forward in router: router_config.txt
service ipfw restart
# Now, from another computer, visit https://srv:1000
# }
# Git gitolite server {
# Reference: http://gitolite.com/gitolite/fool_proof_setup/
portmaster devel/gitolite
# Chose "Create git user" in the config.
# Config gitolite
su - git
gitolite setup -pk /tmp/erikw\@laptop.pub
gitolite list-users
gitolite list-repos
exit # to root shell
# Now verify that we can use the git server from another computer:
# laptop$ git ls-remote git@srv:gitolite-admin
# laptop$ ghq get git@srv:gitolite-admin
# laptop$ ghq look git@srv:gitolite-admin
# Administraton.
# The repo clones in /usr/local/git/repositories are bare, so it needs to be cloned to somewhere.
# Make it convenient by cloning on the same machine.
# NOTE this happens to work as the username ~erikw on server-name is the same for which I set up the gitloite-admin in the beginning. See conf/gitolite.conf.
su - erikw
ssh-keygen.sh # create keys for 'localhost'
exit
su - erikw
ghq get git@localhost:gitolite-admin
ghq get git@localhost:testing
exit
mkdir /root/src
cd /root/src
#* Add a new user:
# First obtain their public ssh key, then add it to the admin repo
## Create a new repo:
## edit conf/gitolite.conf and add the new repo, then commit, push and clone the new repo.
## Delete a repo:
# First remove it from conf/gitolit.conf, then remove the repo dir.
rm -r /usr/local/git/repositories/gitrepotoremove.git
## Rename a repo:
# Reference: http://gitolite.com/gitolite/basic-admin/#removingrenaming-a-repo
# Edit name in conf/gitolite.conf, then rename it on disk. Move on disk first!. Reference: https://stackoverflow.com/a/5164868/265508
mv /usr/local/git/repositories/old_name /usr/local/git/repositories/new_name
# Logs are locate in: /usr/local/git/.gitolite/logs
# }
# taskd {
# Reference: https://gitpitch.com/GothenburgBitFactory/taskserver-setup
# Reference: https://www.vultr.com/docs/install-taskserver-taskd-on-freebsd-11
portmaster deskutils/taskd
cat << EOF > /etc/rc.conf.d/taskd
taskd_enable="YES"
EOF
# Generate server self-signed root CA & cert, server key & cert and server revocation list
cd /usr/local/share/taskd/
cat << EOF > vars
BITS=4096
EXPIRATION_DAYS=365
ORGANIZATION="server-name"
CN=localhost
COUNTRY=DE
STATE="Berlin"
LOCALITY="Berlin"
EOF
./generate.ca
./generate.crl
./generate.server
chown taskd:taskd ca.cert.pem ca.key.pem server.cert.pem server.crl.pem server.key.pem
chmod 400 ca.cert.pem ca.key.pem server.cert.pem server.crl.pem server.key.pem
export TASKDDATA=/var/db/taskd
cd $TASKDDATA
ln -s /usr/local/share/taskd/ca.cert.pem .
ln -s /usr/local/share/taskd/server.cert.pem .
ln -s /usr/local/share/taskd/server.crl.pem .
ln -s /usr/local/share/taskd/server.key.pem .
taskd config server 0.0.0.0:53589
taskd config ca.cert $TASKDDATA/ca.cert.pem
taskd config server.cert $TASKDDATA/server.cert.pem
taskd config server.crl $TASKDDATA/server.crl.pem
taskd config server.key $TASKDDATA/server.key.pem
taskd config log /var/log/taskd.log
taskd config pid.file /var/run/taskd.pid
touch /var/log/taskd.log
chown -R taskd:taskd /var/db/taskd/ /var/log/taskd.log
# Missing instructions on vultr.com
cat << EOF >> /root/profile
# Needed so taskd(1) know where the data is.
export TASKDDATA=/var/db/taskd
EOF
touch /var/run/taskd.pid
chown taskd:taskd /var/run/taskd.pid
cat << EOF >> /etc/rc.conf.d/ipfw
# taskd
firewall_myservices="${firewall_myservices} 53589/tcp"
EOF
service ipfw restart
service taskd start
# Create new user
# Reference: https://taskwarrior.org/docs/taskserver/user.html
taskd add org public
taskd add user public erikw
# Missing from instructions; the user running taskd(1) must own these files:
chown -R taskd:taskd /var/db/taskd/orgs
cd /usr/local/share/taskd/
./generate.client erikw # Take note of the client key.
tar pvczf certs_erikw.tar.gz ca.cert.pem erikw.*
# Copy the tarball to a client machine and set up task client
# laptop$ mkdir -p ~/.task/certs/server-name
# laptop$ cd ~/.task/certs/server-name
# laptop$ scp srv:/usr/local/share/taskd/certs_erikw.tar.gz .
# laptop$ tar xvzf certs_erikw.tar.gz
# laptop$ cat << EOF >> ~/.taskrc
# taskd server: server-name
#taskd.trust=ignore hostname
#taskd.certificate=~/.task/certs/server-name/erikw.cert.pem
#taskd.key=~/.task/certs/server-name/erikw.key.pem
#taskd.ca=~/.task/certs/server-name/ca.cert.pem
#taskd.server=server-name.erikw.me:53589
#taskd.credentials=public/erikw/....
# EOF
# laptop$ task diagnostic # Make sure that in the output CA, Cert, and Key are all "readable".
# laptop$ task sync init
# laptop$ task sync
#
# If it does not work, debug like
# server-name$ taskd server --debug --debug.tls=2
# laptop$ task rc.debug=1 rc.debug.tls=2 sync
# Do the same on server-name
portmaster deskutils/taskwarrior
su - erikw
mkdir -p ~/.task/certs/server-name
cd ~/.task/certs/server-name
cp /usr/local/share/taskd/certs_erikw.tar.gz .
tar xvzf certs_erikw.tar.gz
# Edit ~/.taskrc to set FreeBSD paths.
task sync init
exit # to root sh
# }
# DHCP {
# Reference; https://www.freebsd.org/doc/handbook/network-dhcp.html
portmaster net/isc-dhcp44-server
rm /usr/local/etc/dhcpd6.conf # No IPv6 support needed in local net.
cat << EOF >/usr/local/etc/dhcpd.conf
# Default search domain that will be provided to clients. If a host is called X, it will be searched under x.dom.tld.
# Setting this, enables Android to resolv my local DNS A-records served by unbound. However it means that the FQDN must be used both at Android and Linux, e.g. "srv.", otherwise srv.erikw.me is searched.
# Seems like disabling domain-name setting, it will works using "srv." from Android, and "srv" from Linux devices.
#option domain-name "erikw.me";
# Let ourselves be the DNS server, and add external fallbacks.
#option domain-name-servers 192.168.178.55, 1.1.1.1, 1.0.0.1;
option domain-name-servers 10.0.0.2, 1.1.1.1, 1.0.0.1;
# Subnet mask that will be given to clients
#option subnet-mask 255.0.0.0;
# Lease in seconds.
# Make it really long, so that clients in my home network can survinve for a while if server-name dies.
default-lease-time 10080;
max-lease-time 30240;
# (Temporary) Which logging facility to use for syslog. Need to enable this in /etc/syslog.conf too.
log-facility local1;
# This is the offical DHCp server for the local network.
authoritative;
# Local network definition.
# Let's use a big block! https://en.wikipedia.org/wiki/Private_network
subnet 10.0.0.0 netmask 255.0.0.0 {
# Allocate blocks like this:
# 10.0.0.*/8: Static configurations for my devices.
# 10.0.1.*/8: Static configurations for other person's devices
# 10.0.2.*/8: Dynamic range for DHCP.
range 10.0.2.1 10.0.2.254;
option routers 10.0.0.1;
}
# Static configurations.
## My devices
host laptop-eth {
hardware ethernet ...;
fixed-address 10.0.0.3;
}
EOF
# Disable DHCP server in router: router_config.txt
# Open ports in firwall.
cat << EOF >> /etc/rc.conf.d/ipfw
# isc-dhcpd
firewall_myservices="${firewall_myservices} bootps/udp"
EOF
service ipfw restart
# Set server-name to be statically configured.
cat << EOF > /etc/rc.conf.d/network
# DHCP
#ifconfig_em0="DHCP"
#ifconfig_em0_ipv6="inet6 accept_rtadv"
# Static
# See defaultrouter in /etc/rc.conf.d/routing
# server-name as DHCP server.
ifconfig_em0="inet 10.0.0.2 netmask 255.0.0.0"
# Fritz.box as DHCP server.
#ifconfig_em0="inet 192.168.178.55 netmask 255.255.255.0"
EOF
cat << EOF > /etc/rc.conf.d/routing
# Default destination for static IP configuration.
# Fritz.box as DHCP server.
#defaultrouter="192.168.178.1"
# server-name
defaultrouter="10.0.0.1"
EOF
# Set up some logging
tail -f /var/log/messages
tail -f /var/db/dhcpd/dhcpd.leases
cat << EOF > /etc/syslog.conf
# Temporary isc-dhcpd debug logging.
# To activate:
# $ touch /var/log/dhcpd.log
# $ chown dhpcd /var/log/dhcpd.log
# $ service syslogd restart
# $ service isc-dhcpd restart
local1.*
EOF
portmaster net/tcpdump
tcpdump -n -i em0 port bootps or port bootpc
# Now test it!
service isc-dhcpd onestart
cat << EOF > /etc/rc.conf.d/dhcpd
dhcpd_enable="YES"
dhcpd_flags="-q"
dhcpd_ifaces="em0"
EOF
service isc-dhcpd start
# }
# ZNC {
# A irc bouncer, see https://en.m.wikipedia.org/wiki/BNC_%28software%29
# Reference: https://wiki.znc.in/Installation#FreeBSD
portmaster irc/znc
su -m znc -c 'znc -d /usr/local/etc/znc --makeconf'
#[ .. ] Checking for list of available modules...
#[ ** ]
#[ ** ] -- Global settings --
#[ ** ]
#[ ?? ] Listen on port (1025 to 65534): 6677
#[ ?? ] Listen using SSL (yes/no) [no]: yes
#[ ?? ] Listen using both IPv4 and IPv6 (yes/no) [yes]:
#[ .. ] Verifying the listener...
#[ ** ] Unable to locate pem file: [/usr/local/etc/znc/znc.pem], creating it
#[ .. ] Writing Pem file [/usr/local/etc/znc/znc.pem]...
#[ ** ] Enabled global modules [webadmin]
#[ ** ]
#[ ** ] -- Admin user settings --
#[ ** ]
#[ ?? ] Username (alphanumeric): admin
#[ ?? ] Enter password:
#[ ?? ] Confirm password:
#[ ?? ] Nick [admin]:
#[ ?? ] Alternate nick [admin_]:
#[ ?? ] Ident [admin]:
#[ ?? ] Real name (optional):
#[ ?? ] Bind host (optional):
#[ ** ] Enabled user modules [chansaver, controlpanel]
#[ ** ]
#[ ?? ] Set up a network? (yes/no) [yes]: no
#[ ** ]
#[ .. ] Writing config [/usr/local/etc/znc/configs/znc.conf]...
#[ ** ]
#[ ** ] To connect to this ZNC you need to connect to it as your IRC server
#[ ** ] using the port that you supplied. You have to supply your login info
#[ ** ] as the IRC server password like this: user/network:pass.
#[ ** ]
#[ ** ] Try something like this in your IRC client...
#[ ** ] /server <znc_server_ip> +6677 admin:<pass>
#[ ** ]
#[ ** ] To manage settings, users and networks, point your web browser to
#[ ** ] https://<znc_server_ip>:6677/
#[ ** ]
#[ ?? ] Launch ZNC now? (yes/no) [yes]: yes
#[ .. ] Opening config [/usr/local/etc/znc/configs/znc.conf]...
#[ .. ] Loading global module [webadmin]...
#[ .. ] Binding to port [+6677]...
#[ ** ] Loading user [admin]
#[ >> ] [/usr/local/lib/znc/simple_away.so]
#[ .. ] Adding server [chat.freenode.net +6697 ]...
#[ .. ] Loading user module [chansaver]...
#[ .. ] Loading user module [controlpanel]...
#[ .. ] Forking into the background...
#[ >> ] [pid: 58083]
#[ ** ] ZNC 1.7.0 - https://znc.in
# NOTE znc.conf needs 664 permissions, group must be able to write, othwrise znc won't start.
# Autostart
cat << EOF > /usr/local/etc/rc.conf.d/znc
znc_enable="YES"
EOF
# Open ports in firwall.
cat << EOF >> /etc/rc.conf.d/ipfw
# znc
firewall_myservices="${firewall_myservices} 6677/tcp"
EOF
service ipfw restart
# Set up port forwarding in router to 6677.
# From another computer, visit https://srv:6677/
# webadmin config
## Global Settings
# * Maximum Buffer Size: 1024
# * Global modules to enable: adminlog, fail2ban, lastseen, log, block_motd
## Manage Users
# * [Add]
# - username: erikw
# - nickname: erikw
# - alt nickname: erikw1
# - ident: erikw
# - real name: Erik Westrup
# Modules to enable: chansaver, controlpanel
### Channels
# * Buffer size: 1024
### ZNC Behaviour
# * Timzeon: Europe/Berlin
# * Max IRC Networks Number: 10
# Connect with an IRC client to
# IP: server-name.erikw.me
# port: 6677
# SSL: yes
# username: erikw
# password: ...
#
# E.g. with Irssi:
# * First install the dispatch.pl script so we can send unknonw commands (/znc) to the server: https://wiki.znc.in/Irssi
## Freenode
# irssi> /connect zncRemoteFreenode
# irssi> /znc AddNetwork freenode
# irssi> /znc JumpNetwork freenode
# Prefix the port name with '+' to enable SSL connection.
# irssi> /znc AddServer chat.freenode.net +7000
# irssi> /znc connect
### Set up nickname identiy. Reference: https://wiki.znc.in/Perform#Bitlbee
# First go to the web UI and enable the perform module for this network (not for the user, as that sends those commands to all networks)
# irssi> /msg *perform add PRIVMSG NickServ@services. :IDENTIFY .....
# irssi> /msg *perform list
# irssi> /msg *perform execute
#
### Join channels
# irssi> /join #vim
# irssi> /join ##archlinux
## Quakenet
# irssi> /znc AddNetwork quakenet
# irssi> /znc JumpNetwork quakenet
# irssi> /znc AddServer irc.quakenet.org 6667
# irssi> /znc connect
# irssi> /msg *perform add PRIVMSG Q@CServe.quakenet.org :AUTH erikw .....
# irssi> /msg *perform execute
## EFNet
# irssi> /znc AddNetwork efnet
# irssi> /znc JumpNetwork efnet
# irssi> /znc AddServer efnet.portlane.se 6667
# irssi> /znc connect
# irssi> /join #blausoffan
# irssi> /join #dwww
# irssi> /msg *perform add PRIVMSG Q@CServe.quakenet.org :auth erikwestrup .....
# Now connect to a network by changing the irssi config to connect with
# username: erikw/freenode
# To change global settings:
# irssi> /msg *controlpanel help
# Enable fail2ban when all configs are stable.
# Push notifications: znc-push {
# NOTE I scripted this to bin/znc_push_recompile.sh
su - erikw
ghq get git@github.com:jreese/znc-push.git
^get^look
znc-buildmod push.cpp
exit # to root sh
cp /home/erikw/src/github.com/jreese/znc-push/push.so /usr/local/lib/znc/
# Load module:
# irssi> /msg *status loadmod --type=user push
# Also enable it in the webadmin: https://srv:6677/mods/global/webadmin/edituser?user=erikw
# Set up push service: PushBullet
# The only one I was able to get to work or that is free.
# 1) Get my access token at: https://www.pushbullet.com/#settings/account
# 2) Find my device ID:
# $ curl --header 'Access-Token: .....' https://api.pushbullet.com/v2/devices | jq ".
# 3) Test to send notification to all devices:
$ curl --header 'Access-Token: .....' --header 'Content-Type: application/json' --data-binary '{"body":"Space Elevator, Mars Hyperloop, Space Model S (Model Space?)","title":"Space Travel Ideas","type":"note"}' --request POST https://api.pushbullet.com/v2/pushes | jq "."
# 4) Now configure znc-push
# irssi> /msg *push set service pushbullet
# irssi> /msg *push set secret ...
# irssi> /msg *push set target ....
# irssi> /msg *push get
# 5) Now try by connecting with another irc client to the same network I'm in, and start a private chat. Then a PushBullet notification should appear.
# }
# Bitlbee {
portmaster irc/bitlbee
# NOTE I skipped this in the end, as the list of protocols supported is not long, and the supported ones are 3rd party that I epxect to break often - not something I want to commit to maintain.
# Supported protocols: https://wiki.bitlbee.org/
# }
# NOTE on 2019-11-18 I disabled ZNC like this:
# * Remove /etc/pf.conf rules
# $ service znc stop
# edit znc_enable="NO" in /usr/local/etc/rc.conf.d/znc
# }
# iodine IP-over-DNS tunneling {
# Reference: https://code.kryo.se/iodine/README.html
portmaster net/iodine
cat << EOF > /usr/local/etc/rc.conf.d/iodined
iodined_enable="YES"
# Tunnel password
iodined_password="<pw>"
# Tunnel domain. "i" as in "iodine".
iodined_domain="i.erikw.me"
EOF
# Test connection
## server
# Switch over local unbound server to listen on port 9953, and tell iodine to forward all non-tunneled traffic to the local DNS server
patch << EOF
--- /usr/local/unbound/unbound.conf
- port: 53
+ port: 9953
EOF
service unbound restart
iodined -b 9953 -f 172.16.0.0 test.com
# If server command has already executed once, it might fail the next time with: "route already in table"
# then
# $ ifconfig tun0 down
# $ ifconfig tun0 destroy
# $ netstat -r
# $ route delete -net 172.16.0.0/27 172.16.0.0
## Client: laptop
# laptop$ pacman -S iodine
# laptop$ iodine -f -r srv test.com
# If this failes with: "iodine" open_tun: /dev/net/tun: No such device: No such device
# then try reboot the computer.
#
# laptop$ ip addr show dev dns0
# laptop$ ping ping 172.16.0.1
# To get this to work for real, I must create a subdomain to erikw.me, say i.erikw.me, and delegate the nameserver to point to server-name.
# Howevery Loopia does not allow NS delegration of subdomains. Options:
# * Switch to another provider which does, e.g.: http://freedns.afraid.org/
# * Delegate all NS at erikw.me to my server, and run an authorative DNS server on server-name, like bind.
# }
# OpenVPN {
# Reference: https://openvpn.net/index.php/open-source/documentation/howto.html
# Reference: https://www.digitalocean.com/community/tutorials/how-to-set-up-an-openvpn-server-on-ubuntu-16-04
# Setting up "routed VPN" is probably enough, I don't need access to link layer that is given with "bridged VPN".
portmaster security/openvpn
cat << EOF > /usr/local/etc/rc.conf.d/openvpn
openvpn_enable="YES"
EOF
## Generate certs {
# Generate the master Certificate Authority (CA) certificate & key
# Reference: https://community.openvpn.net/openvpn/wiki/EasyRSA3-OpenVPN-Howto
# But for the easyrsa part, use: https://community.openvpn.net/openvpn/wiki/EasyRSA3-OpenVPN-Howto
# or https://github.com/OpenVPN/easy-rsa/blob/v3.0.5/README.quickstart.md
#
mkdir -p /usr/local/etc/easy-rsa/openvpn
cp -r /usr/local/share/easy-rsa/* /usr/local/etc/easy-rsa/openvpn
cd /usr/local/etc/easy-rsa/openvpn
cat << EOF >>vars
set_var EASYRSA_REQ_COUNTRY "DE"
set_var EASYRSA_REQ_PROVINCE "Berlin"
set_var EASYRSA_REQ_CITY "Berlin"
set_var EASYRSA_REQ_ORG "server-name"
set_var EASYRSA_REQ_EMAIL "user@gmail.com"
set_var EASYRSA_REQ_OU "SRV"
set_var EASYRSA_CERT_EXPIRE 730
EOF
# NOTE the tutorials advice separating ca, server and client. But I'm all of those, so I'm reusing the same directoires.
## CA certs
./easyrsa.real init-pki
./easyrsa.real build-ca
# Enter strong password, and common name = openvpn_ca_server-name
## Server certs
./easyrsa.real gen-req openvpn_server_server-name nopass
## Client certs
./easyrsa.real gen-req openvpn_client_laptop
./easyrsa.real gen-req openvpn_client_phone1 nopass # NOTE don't do nopass, then it's easy for someone to use my VPN by just stealing the cert!
./easyrsa.real gen-req openvpn_client_laptop2
## Inspect requests
./easyrsa.real show-req server-name_openvpn_server
./easyrsa.real show-req openvpn_client_laptop
./easyrsa.real show-req openvpn_client_phone1
./easyrsa.real show-req openvpn_client_laptop2
## Sign requests
./easyrsa.real sign-req server openvpn_server_server-name
./easyrsa.real sign-req client openvpn_client_laptop
./easyrsa.real sign-req client openvpn_client_phone1
./easyrsa.real sign-req client openvpn_client_laptop2
./easyrsa.real show-cert openvpn_server_server-name
./easyrsa.real show-cert openvpn_client_laptop
./easyrsa.real show-cert openvpn_client_phone1
./easyrsa.real show-cert openvpn_client_laptop2
## Troubleshooting {
# Client hangs on Auth step: check server logs for expired dates
grep expired /var/log/openvpn.log
# Control cert expiry date:
./easyrsa.real show-cert openvpn_client_phone1 | grep Validity -A 2
openssl x509 -text -noout -in pki/ca.crt | grep Validity -A 2
# If clients gets stuck on Auth and /var/log/openvpn.log show
# VERIFY ERROR: depth=0, error=CRL has expired: CN=openvpn_client_laptop2
# then it means that the CRL file must be re-created:
./easyrsa.real gen-crl
service openvpn restart
## }
# Generate DH (diffie hellman) paramenters used for TLS handshake.
./easyrsa.real gen-dh
# Generate tls-auth key
/usr/local/sbin/openvpn --genkey --secret /usr/local/etc/openvpn/ta.key
# Revoke a cert:
./easyrsa.real revoke openvpn_client_phone1
# Update revoke list
./easyrsa.real gen-crl
# }
## Config for server {
mkdir /usr/local/etc/openvpn
cp /usr/local/share/examples/openvpn/sample-config-files/server.conf /usr/local/etc/openvpn/openvpn.conf
patch << EOF
--- /usr/local/etc/openvpn/openvpn.conf
+ca /usr/local/etc/easy-rsa/openvpn/pki/ca.crt
+cert /usr/local/etc/easy-rsa/openvpn/pki/issued/openvpn_server_server-name.crt
+key /usr/local/etc/easy-rsa/openvpn/pki/private/openvpn_server_server-name.key
+dh /usr/local/etc/easy-rsa/openvpn/pki/dh.pem
+# I already use 10.0.0.0 for my DHCP net, so let's put VPN clients in a sublock of the 172.16.0.0/12 block -> 172.16.123.0/24
+server 172.16.123.0 255.255.255.0
+push "redirect-gateway def1 bypass-dhcp"
+push "dhcp-option DNS 172.16.123.1"
+push "dhcp-option DNS 1.1.1.1"
+tls-auth /usr/local/etc/openvpn/ta.key 0
-;user nobody
-;group nobody
+user nobody
+group nobody
+# Verify client certificates against the CRL list:
+crl-verify /usr/local/etc/easy-rsa/openvpn/pki/crl.pem
EOF
# Server must be set to forward IP traffic:
sysctl net.inet.ip.forwarding
sysctl net.inet.ip.forwarding=1
cat << EOF >> /etc/sysctl.conf
# Allow IP forwarding for OpenVPN:
sysctl net.inet.ip.forwarding=1
EOF
# Routing must also be enabled
cat << EOF >>/etc/rc.conf.d/routing
# Enable routing functionality so OpenVPN incoming traffic can be routed out of the virtual network.
# This also required $(sysctl net.inet.ip.forwarding=1).
gateway_enable="YES"
EOF
service routing restart
# Open on router for UDP on port 1194
# Open ports in firwall.
cat << EOF >> /etc/rc.conf.d/ipfw
# OpenVPN
firewall_myservices="${firewall_myservices} 1194/udp"
EOF
service ipfw restart
# Update unbound to allow DNS resolution from virtual network.
patch << EOF
--- /usr/local/unbound/unbound.conf
+# Serve OpenVPN clients
+interface: 172.16.123.1
+# Allow OpenVPN clients
+access-control: 172.16.123.0/24 allow
EOF
service unbound restart
# However unbound will fail at boot if tun0 is not available.
# Fix 1) set rc boot order.
# Advantage: we can disable unbound and things still work.
# Disadvantage: openvpn file might be updated by package upgrade and we need to update it.
patch << EOF
--- /usr/local/etc/rc.d/openvpn
+# BEFORE: unbound
EOF
# Fix 2) add a post command to openvpn to start unbound
# Advantage: Only modify user conf files
# Disadvantage: What if we disable unbound, then this command will fail.
cat << EOF >>/usr/local/etc/rc.conf.d/openvpn
openvpn_flags='--up "service unbound start"'
EOF
# I went with Fix 1.
# Try server
openvpn --config /usr/local/etc/openvpn/openvpn.conf
# or
service openvpn start
# Check that new interface is up:
ifconfig tun0
netstat -r
# }
## Config for client {
mkdir -p /usr/local/etc/openvpn/client-configs/files
chmod 700 /usr/local/etc/openvpn/client-configs/files
cp /usr/local/share/examples/openvpn/sample-config-files/client.conf /usr/local/etc/openvpn/client-configs/base.conf
patch << EOF
--- /usr/local/etc/openvpn/client-configs/base.conf
-remote my-server-1 1194
+remote server-name.erikw.me 1194
-;user nobody
-;group nobody
+user nobody
+group nobody
-ca ca.crt
-cert client.crt
-key client.key
+#ca ca.crt
+#cert client.crt
+#key client.key
+# For Linux system who as update-resolv-conf to parse DHCP options from openvpn to update resolv.conf to set correct DNS server.
+# NOTE If this generated file is for Linux, uncomment these lines below.
+#script-security 2
+#up /etc/openvpn/update-resolv-conf
+#down /etc/openvpn/update-resolv-conf
EOF
# Create client generation script.
cat << EOF > /usr/local/etc/openvpn/client-configs/make_config.sh
#!/usr/bin/env bash
# First argument: Client identifier used when signing easyrsa certs.
clientid="$1"
PKI_DIR=/usr/local/etc/easy-rsa/openvpn/pki
OUTPUT_DIR=/usr/local/etc/openvpn/client-configs/files
BASE_CONFIG=/usr/local/etc/openvpn/client-configs/base.conf
OPENVPN_DIR=/usr/local/etc/openvpn
cat ${BASE_CONFIG} \
<(echo -e '<ca>') \
${PKI_DIR}/ca.crt \
<(echo -e '</ca>\n<cert>') \
${PKI_DIR}/issued/${clientid}.crt \
<(echo -e '</cert>\n<key>') \
${PKI_DIR}/private/${clientid}.key \
<(echo -e '</key>\n<tls-auth>') \
${OPENVPN_DIR}/ta.key \
<(echo -e '</tls-auth>') \
> ${OUTPUT_DIR}/${clientid}.ovpn
EOF
chmod 744 /usr/local/etc/openvpn/client-configs/make_config.sh
# Generate client configs
cd /usr/local/etc/openvpn/client-configs
./make_config.sh openvpn_client_laptop
./make_config.sh openvpn_client_phone1
./make_config.sh openvpn_client_laptop2
ls -lrt files
# Seems like a restart of the server is needed for it to know about new certs?
service openvpn restart
# Copy it over to main computer
cp /files/openvpn_client_laptop2.ovpn /home/erikw/tmp
# From main computer
# laptop$ scp srv:tmp/openvpn_client_laptop2.ovpn ~/dropbox/tmp
# On mobile phone: find file in Dropbox > Export > Save to device > open up in VPN client app > save passphrase to keychain> Save to device > open up in VPN client app > save passphrase to keychain > rename client config to be just "server-name" > set up autoconnect != on local home wifi
## laptop (Arch Linux)
# scp the .ovpn file to laptop
# Uncomment the linux lines in the config part of the file.
# laptop$ sudo -i
# Try it:
# laptop$ openvpn --config openvpn_client_laptop.ovpn
# laptop$ ping 172.16.123.1
# Install it:
# laptop$ mv openvpn_client_laptop.ovpn /etc/openvpn/client/server-name.conf
# Starting the service does not ask for passphrase though; https://unix.stackexchange.com/questions/444855/systemd-ask-password-prompt-not-displayed-for-vpn
# laptop$ systemctl start openvpn-client@server-name
# laptop$ cat << EOF >>/root/.bashrc
# alias vpn_server-name_start='openvpn --config /etc/openvpn/client/server-name.conf'
# EOF
## mac (macOS)
# * For CLI, same as arch.
# mac$ openvpn --config /etc/openvpn/client/server-name.conf
# * For GUI e.g. Tunnelblick, als copy over the ta.key as the installer can't find the embeded one in the .ovpn file.
## phone1
# transfer the .ovpn file to phone1 some how (ssh -> laptop -> dropbox). After importing it, rename the profile to "server-name".
# The good Android OpenVPN client is called "OpenVPN for Android": https://play.google.com/store/apps/details?id=de.blinkt.openvpn
# Look at trafic from the server side with
tcpdump -i tun0 icmp
# }
# }
# Jails {
# Reference: https://www.freebsd.org/doc/handbook/jails-build.html
# Using traditinal jails seems very cumbersome -> use a helper: https://github.com/iocage/iocage
# Reference: https://dan.langille.org/2015/03/07/getting-started-with-iocage-for-jails-on-freebsd/
# Reference: https://iocage.readthedocs.io/en/latest/
portmaster sysutils/iocage
# Activate iocage on my zfs pool $(zpool list).
iocage activate zroot
# Fetch base system.
iocaeg fetch
# Chose 11.1-RELEASE. NOTE you must fest a version that is same or lower than host $(freebsd-version).
zfs list | grep iocage
mount -t fdescfs null /dev/fd
# NOTE don't add this to fstab, it does not work to boot system them.
# iocage complains about it though, -- how to fix?
cat << EOF >>/etc/fstab
# Recommended by iocage-create. See fdescfs(5).
fdescfs /dev/fd fdescfs rw 0 0
EOF
cat << EOF >/usr/local/etc/rc.conf.d/iocage
iocage_enable="YES"
EOF
# Set up NAT for jails
patch << EOF
--- /etc/pf.conf
+jails_subnet = "192.168.5.0/24"
+# Jails NAT
+nat on $ext_if inet from $jails_subnet to any -> $ext_if
+pass inet proto icmp from $jails_subnet to any keep state
EOF
service pf reload
# TODO add tl;dr instructions on how to update jail.
# Reference: https://iocage.readthedocs.io/en/latest/advanced-use.html
# }
# Webserver in Jail {
# Create in a jail with iocage with.
# Let's allocate 192.168.5.0/24 for jails.
iocage create -n webserver ip4_addr="em0|192.168.5.1/24" -r 12.0-RELEASE
iocage list
# Allow ping from within jail.
iocage set allow_raw_sockets=1 webserver
# Start this jail on boot
iocage set boot=on webserver
iocage get boot webserver
iocage get -a webserver
iocage set notes="Isolated websesrver" webserver
# Must set DNS server explicily. Otherwise the hosts /etc/resolv.conf gets copied, which uses 127.0.0.0 as nameserver, which does not work from wihin the jail.
iocage set resolver=10.0.0.2 webserver
# Set up unbound to allow connection from jail.
patch << EOF
--- /usr/local/etc/unbound/unbound.conf
+# Jail: webserver
+# For some reasons it does not work to set the whole netblock 192.168.5.0/24.
+access-control: 192.168.5.1 allow
EOF
service unbound restart
# Start jail
iocage start webserver
# Execute command from root sh in jail.
iocage exec webserver ifconfig
# Jump in!
iocage console webserver
# Test networkg config
ping google.com
pkg install bash # so iocage chroot can work.
pkg install nginx
service start nginx
exit # to rootsh
# Must enable forwarding for port 80 from host OS to the jail in /etc/pf.conf, still including the NAT setup in pf.conf for jails above.
# Reference: http://kbeezie.com/freebsd-jail-single-ip/
patch << EOF
--- /etc/pf.conf
# Open connection to specific ports to static Jail.
IP_PUB="10.0.0.2"
IP_JAIL="192.168.5.1"
NET_JAIL="192.168.5.0/24"
PORT_JAIL="80"
scrub in all
nat pass on $ext_if from $NET_JAIL to any -> $IP_PUB
rdr pass on $ext_if proto tcp from any to $IP_PUB port $PORT_JAIL -> $IP_JAIL
EOF
# Also remove www from $tcp_ingress normal rule.
service pf reload
# Set up cloned IF
cat << EOF >>/etc/rc.conf.d/network
# Jails
# Cloned interface to set up shared Jails IPs on
cloned_interfaces="lo1"
ipv4_addrs_lo1="192.168.5.1-9/24"
EOF
service netif restart
# Now visit http://10.0.0.2:80 and it should go to jail's /usr/local/www/nginx/html.index!
# NOTE I aborted setup here, as it would make my git hook deployment and certbot update more complicated. Still possible but KISS.
# Uninstall iocage
iocage stop webserver
iocage destory --recursive webserver
iocage clean --all
zfs destroy zroot/iocage
umount fdescfs
pkg delete py36-iocage
# }
# Webserver (nginx) {
portmaster www/nginx
mkidr /usr/local/etc/rc.conf.d
cat << EOF >/usr/local/etc/rc.conf.d/nginx
nginx_enable="YES"
EOF
# Add "www" for TCP ingress in /etc/pf.conf
# Forward port 80 in router.
# Create our own web root.
rm /usr/local/www/nginx
mkdir /usr/local/www/nginx
chmod 555 /usr/local/www/nginx
# Now create a local git repo in gitolite and set up so it can install to the www directory.
# see repo www.erikw.me
# Set server name:
patch << EOF
--- /usr/local/etc/nginx/nginx.conf
server {
-server_name localhost;
+server_name erikw.me www.erikw.me server-name.erikw.me;
}
+# Redirect (www|server-name).erikw.me -> erikw.me permanently.
+server {
+ server_name www.erikw.me server-name.erikw.me;
+ return 301
+ $scheme://erikw.me$request_uri;
+}
EOF
service nginx start
# Now visit erikw.me from another computer.
# Automatic deploy from git-push {
# Reference: https://demonastery.org/2012/09/a-hooking-system-for-gitolite/
# Prepare gitolite
patch << EOF
--- /usr/local/git/.gitolite.rc
-GIT_CONFIG_KEYS => '',
+GIT_CONFIG_KEYS => '.*',
+LOCAL_CODE => "$ENV{HOME}/.gitolite/local-code",
EOF
gitolite setup
# Both root and git user needs to have ssh keys so they can clone and update the nginx repo.
ssh-keygen
su - git
ssh-keygen
exit # to rootsh
# Set up gitlote-admin
su erikw
cd ~/src/localhost/gitolite-amdin
mkdir -p local-code/hooks/common/hooks.d
# Create a hook executor.
cat << EOF >local-code/hooks/common/post-receive
#!/usr/bin/env bash
# set -x
run_hook () {
echo -en "\e[1;33m$4..\e[00m "
echo $1 $2 $3 | $GIT_DIR/hooks/hooks.d/$4
}
echo -en "\e[1;33mRunning hooks..\e[00m "
while read oldrev newrev refname; do
if [ "$refname" = "refs/heads/master" ]; then
hooks=$(git cat-file blob $newrev:.hooks 2>/dev/null)
if [ -n "$hooks" ]; then
# Repo-local hooks defined in .hooks.
for hook in $hooks; do
run_hook $oldrev $newrev $refname $hook
done
fi
# Global hooks for this repo (ie. set in Gitolite config).
hooks=$(git config --get hooks.run)
[ -z "$hooks" ] && continue
for hook in $hooks; do
run_hook $oldrev $newrev $refname $hook
done
fi
done
echo -e "\e[1;32mDone.\e[00m"
EOF
chmod 744 local-code/hooks/common/post-receive
# Create our nginx deploy script
cat << EOF >local-code/hooks/common/hooks.d/nginx-deploy
#!/usr/bin/env sh
# Update existing clone of git repo.
#set -x
DESTDIR=/usr/local/www/nginx
unset GIT_DIR # This is set, which must be unset to be able to work on another git repo.
echo "Updating $DESTDIR to latest revision."
cd $DESTDIR
git fetch
git rebase
# www user must be able to read files.
chmod -R o+r $DESTDIR
# But not git...
chmod -R o-r $DESTDIR/.git
EOF
chmod 744 local-code/hooks/common/hooks.d/nginx-deploy
# add root@server-name.pub and git@server-name.pub to keydir
# Set up which repo to use this new hook
patch << EOF
--- conf/gitolite.conf
repo www.erikw.me
- RW+ = erikw
+ RW+ = erikw root git
+ config hooks.run = nginx-deploy
EOF
git commit -m "Hooks for nginx deploy"
git push origin master
exit # to rootsh
# Make the initial clone of the repo
cd /usr/local/www
git clone git@localhost:www.erikw.me nginx
chown -R git:git nginx
# Now when doing git-push in rep www.erikw.me, the hook will run!
#}
# HTTPS with TLS cert {
# Reference: https://certbot.eff.org/lets-encrypt/freebsd-nginx
portmaster security/py-certbot
certbot certonly --webroot -w /usr/local/www/nginx -d erikw.me -d www.erikw.me -d server-name.erikw.me
service nginx reload
# If cert is expired in webbrowser, but $(certbot renew) says it's still good, then
# $ certbot renew --force-renew
# $ service nginx reload
# Enable cronjob to execute $(certbot renew)
cat << EOF >/etc/periodic.conf
# Certbot cert renewal.
# See /usr/local/etc/periodic/weekly/500.certbot
weekly_certbot_enable=yes
# Service to start and stop between updates.
weekly_certbot_service=nginx
EOF
# Let's test it
/usr/local/etc/periodic/weekly/500.certbot
## Wildcard cert {
# NOTE I wanted to get a wildcard cert for *.erikw.me, so I can HTTP redirect subdomains with HTTPS.
# Reference: https://blogs.msdn.microsoft.com/mihansen/2018/03/15/creating-wildcard-ssl-certificates-with-lets-encrypt/
# The down-side of this is that $(certbot renew) can't automatically renew this, as it has no way to update DNS record challenge, unless a plugin/custom script is used for this. To renew these certs, one has to re-run the original $(certbot certonly) command.
# Reference: https://github.com/certbot/certbot/issues/6280
# Delete existing
certbot delete
certbot certonly --server https://acme-v02.api.letsencrypt.org/directory -w /usr/local/www/nginx --preferred-challenge dns --manual -d erikw.me -d '*.erikw.me'
# Do the DNS TXT records. Then update nginx.conf to use the new directory (if forgot to $(certbot delete) before this step).
# There's a plugin for LoopiaDNS to update cert with DNS challenge!
# https://github.com/runfalk/certbot-loopia
pip3 install certbot-loopia
cat << EOF >/usr/local/etc/loopiaapi.ini
certbot_loopia:auth_user = erikw@loopiaapi
certbot_loopia:auth_password = passwordgoeshere
EOF
chmod 600 /usr/local/etc/loopiaapi.ini
certbot certonly --server https://acme-v02.api.letsencrypt.org/directory --authenticator certbot-loopia:auth --certbot-loopia:auth-credentials /usr/local/etc/loopiaapi.ini -d erikw.me -d '*.erikw.me'
# Unfortunately this did not work, so I reverted to the non-wildcard cert, so that I don't have to manually update DNS records every month.
##}
#
# Make IP forwardin in router for 443/tcp
# Let through in firewall:
cat << EOF >/usr/local/etc/nginx/nginx.conf
#user nobody;
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
#gzip on;
# http
#server {
# listen 80;
# server_name erikw.me;
# #charset koi8-r;
# #access_log logs/host.access.log main;
# location / {
# root /usr/local/www/nginx;
# index index.html index.htm;
# }
# #error_page 404 /404.html;
# # redirect server error pages to the static page /50x.html
# #
# error_page 500 502 503 504 /50x.html;
# location = /50x.html {
# root /usr/local/www/nginx-dist;
# }
# # proxy the PHP scripts to Apache listening on 127.0.0.1:80
# #
# #location ~ \.php$ {
# # proxy_pass http://127.0.0.1;
# #}
# # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
# #
# #location ~ \.php$ {
# # root html;
# # fastcgi_pass 127.0.0.1:9000;
# # fastcgi_index index.php;
# # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# # include fastcgi_params;
# #}
# # deny access to .htaccess files, if Apache's document root
# # concurs with nginx's one
# #
# #location ~ /\.ht {
# # deny all;
# #}
#}
# HTTPS
server {
listen 443 ssl;
server_name erikw.me;
ssl_certificate /usr/local/etc/letsencrypt/live/erikw.me/fullchain.pem;
ssl_certificate_key /usr/local/etc/letsencrypt/live/erikw.me/privkey.pem;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
root /usr/local/www/nginx;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/local/www/nginx-dist;
}
}
# Redirect all http -> https
# Reference: https://bjornjohansen.no/redirect-to-https-with-nginx
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 301 https://$host$request_uri;
}
# HTTP: Redirect (www|server-name).erikw.me -> erikw.me permanently.
server {
listen 80;
server_name www.erikw.me server-name.erikw.me;
return 301 $scheme://erikw.me$request_uri;
}
# HTTPS: Redirect (www|server-name).erikw.me -> erikw.me permanently.
server {
listen 443 ssl;
server_name www.erikw.me server-name.erikw.me;
return 301 $scheme://erikw.me$request_uri;
}
}
EOF
# To renew certs, just do
certbot renew
# Let's automate this:
cat << EOF >/etc/cron.d/certbot-renew
SHELL=/bin/sh
PATH=/etc:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
# Update TLS certs. Run it at midnight and noon, per recommendation.
# Reference:https://certbot.eff.org/lets-encrypt/freebsd-nginx
0 0,12 * * * cron_mail -s "certbot renew" "python3.6 -c 'import random; import time; time.sleep(random.random() * 3600)' && certbot renew -q"
EOF
# }
# Access log stats{
# Get stats based on access log
portmaster sysutils/goaccess
goaccess --log-format=COMBINED /var/log/nginx/access.log
# }
# }
# }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment