.. title: RaspBSD on Raspberry Pi 2 Model B .. slug: raspbsd-on-raspberry-pi-2-model-b .. date: 2015-10-14 04:52:03 UTC .. updated: 2016-01-30 02:48:51 UTC .. tags: freebsd, mac os x, raspberry pi .. category: .. link: .. description: .. type: text I bought a `Raspberry Pi 2 Model B from CanaKit `_ to install and learn FreeBSD. Fortunately for me (and you) `RaspBSD `_ is available. I found at one point that using an 8GB Micro SD card caused me headaches as I ran out of disk space at some points. I would recommend buying a bigger card. This guide was created using OS X 10.10 (Yosemite) as the "client". All instructions assume: * Correct software installed on OS X * You know how to use Disk Utility and CLI * You have already assembled the Raspberry Pi (RPi) hardware (case, etc.) * WiFi USB adapter is not connected initially (it's configured later) * Ethernet, HDMI, keyboard, mouse are connected to Raspberry Pi * USB to TTL serial cable is available for use (I bought this one: http://www.amazon.com/gp/product/B00QT7LQ88) * Drivers from http://prolificusa.com/pl-2303hx-drivers/ WARNING: This is a "living document" and will be updated as I learn from my mistakes. There may be a lot of errors in this doc so all the standard disclaimers apply. .. TEASER_END: Read more .. contents:: Download and Install ------------------------------------------ Download the latest image. It was 292991 at the time of writing. :: user@host ~ $ cd ~/Downloads user@host ~/Downloads $ curl -O http://download.raspbsd.org/FreeBSD-armv6-11.0-RPI2-292991.img.gz user@host ~/Downloads $ gunzip FreeBSD-armv6-11.0-RPI2-292991.img.gz Insert a MicroSD card in the card reader and using "Disk Utility" unmount it. Do not eject it. Get the name of the MicroSD card. On my machine it was /dev/disk2. :: user@host ~/Downloads $ diskutil list Write the RaspBSD image to the MicroSD card (/dev/disk2). WARNING: Be very careful where you're writing the image because you don't want to overwrite any other disk. :: user@host ~/Downloads $ diskutil unmountDisk /dev/rdisk2 user@host ~/Downloads $ sudo dd if=FreeBSD-armv6-11.0-RPI2-292991.img of=/dev/rdisk2 bs=1m && sync When the image has been written, unmount and eject in *Disk Utility*. :: user@host ~/Downloads $ diskutil eject /dev/rdisk2 Insert the MicroSD card in the RPi. First Boot ------------------------------------------ Power on RPi and let it boot up to the login prompt. Login as user *raspberry* and password *raspberry*. :: % uname -a FreeBSD rpi2 11.0-CURRENT FreeBSD 11.0-CURRENT #0 r292991: Fri Dec 4 16:49:10 MST 2015 brd@hive.raspbsd.org:/usr/local/raspbsd/obj/RPI2/obj/arm.armv6/usr/local/raspbsd/src/common/sys/RPI2 arm Install pkgng ------------------------------------------ ``su`` as user root and install pkgng. You'll not be asked for root password. :: % su - root@rpi2:~ # pkg update The package management tool is not yet installed on your system. Do you want to fetch and install it now? [y/N]: y Since pkgng is not installed you'll be prompted to install it. Say yes. :: root@rpi2:~ # pkg update root@rpi2:~ # pkg upgrade Install useful tools. :: root@rpi2:~ # pkg install tmux vim-lite Enable IPv6 on All Network Interfaces ------------------------------------------ My network has IPv6 support but the interface didn't show an IPv6 address in use. :: root@rpi2:~ # ifconfig lo0: flags=8049 metric 0 mtu 16384 options=600003 inet6 ::1 prefixlen 128 inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1 inet netmask 0xff000000 groups: lo nd6 options=21 ue0: flags=8843 metric 0 mtu 1500 options=80001 ether ab:ab:ab:01:01:01 inet netmask 0xffffff00 broadcast media: Ethernet autoselect (100baseTX ) status: active nd6 options=29 Here *ue0* is my Ethernet interface. As is visible, there's no IPv6 address. Add the following lines to */etc/rc.conf* :: ipv6_activate_all_interfaces="YES" ifconfig_ue0_ipv6="inet6 accept_rtadv" rtsold_enable="YES" Restart networking. If you're connected by SSH your session may be dropped. You can use a tmux or screen session to do this for you. :: root@rpi2:~ # service netif restart Now you should see IPv6 addresses on *l0* and *ue0* interfaces. If you don't, I found ``reboot``-ing worked. :: root@rpi2:~ # ifconfig lo0: flags=8049 metric 0 mtu 16384 options=600003 inet6 ::1 prefixlen 128 inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1 inet netmask 0xff000000 groups: lo nd6 options=23 ue0: flags=8843 metric 0 mtu 1500 options=80001 ether ab:ab:ab:01:01:01 inet6 fe80::abab:abff:fe01:0101%ue0 prefixlen 64 scopeid 0x2 inet6 2601::abab:abff:fe01:0101 prefixlen 64 autoconf inet6 fd85::abab:abff:fe01:0101 prefixlen 64 autoconf inet netmask 0xffffff00 broadcast media: Ethernet autoselect (100baseTX ) status: active nd6 options=23 Enable IPv6 Privacy Features ++++++++++++++++++++++++++++++++++++++++++ An important privacy feature in IPv6 is to create and use temporary addresses. They are disabled by default and you need to enable them. First check the current status. :: root@rpi2:~ # sysctl net.inet6.ip6.use_tempaddr net.inet6.ip6.use_tempaddr: 0 root@rpi2:~ # sysctl net.inet6.ip6.prefer_tempaddr net.inet6.ip6.prefer_tempaddr: 0 Set new values to enable use of temporary addresses. :: root@rpi2:~ # sysctl net.inet6.ip6.use_tempaddr=1 net.inet6.ip6.use_tempaddr: 0 -> 1 root@rpi2:~ # sysctl net.inet6.ip6.prefer_tempaddr=1 net.inet6.ip6.prefer_tempaddr: 0 -> 1 Restart networking. You should see new IPv6 addresses on *ue0* interface after the OS deals with the Route Advertisement and configures its IPv6 addresses. :: root@rpi2:~ # service netif restart root@rpi2:~ # sleep 120 root@rpi2:~ # ifconfig lo0: flags=8049 metric 0 mtu 16384 options=600003 inet6 ::1 prefixlen 128 inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1 inet netmask 0xff000000 groups: lo nd6 options=23 ue0: flags=8843 metric 0 mtu 1500 options=80001 ether ab:ab:ab:01:01:01 inet6 fe80::abab:abff:fe01:0101%ue0 prefixlen 64 scopeid 0x2 inet6 2601::abab:abff:fe01:0101 prefixlen 64 autoconf inet6 2601::a897:3f8c:c8b0:dab9 prefixlen 64 tentative autoconf temporary inet6 fd85::abab:abff:fe01:0101 prefixlen 64 autoconf inet6 fd85::a897:3f8c:c8b0:dab9 prefixlen 64 tentative autoconf temporary inet netmask 0xffffff00 broadcast media: Ethernet autoselect (100baseTX ) status: active nd6 options=23 When you're sure everything's working as intended, you should make these changes permament by adding these lines to */etc/sysctl.conf*. :: net.inet6.ip6.use_tempaddr=1 net.inet6.ip6.prefer_tempaddr=1 Now when you reboot these changes will stick. Copy SSH File ------------------------------------------ From your OS X (or Linux) box make it easy to login without entering your password all the time. :: $ ssh-copy-id -i ~/.ssh/id_rsa Of course, use the IP of your RPi2 box. Upgrade Base System ------------------------------------------ TODO: What's the ideal way to upgrade the base system? Is it ``freebsd-update fetch install``? That doesn't work yet. * `FreeBSD Handbook: Tracking a Development Branch `_ * `FreeBSD Handbook: Using Subversion `_ WARNING: As of January 20, 2016, there is a blocking issue with upgrading from source on RPi2. Follow the discussion on FreeBSD-ARM mailing list: `make buildworld failed with error "relocation truncated to fit: R_ARM_JUMP24 against symbol _fini'" `_. I tested with revision 294969 (January 30) and it was working again. Apparently, it's an issue with adding support for clang 3.8.0 and it will fail again when clang 3.8.0 is imported to base. Download Sources ++++++++++++++++++++++++++++++++++++++++++ :: $ su - # pkg update # pkg install ca_root_nss # which -a svnlite /usr/bin/svnlite # svnlite checkout svn://svn.freebsd.org/base/head /usr/src Possible Errors and Fix ++++++++++++++++++++++++++++++++++++++++++ Although I do not recommend it, if instead of *svn* you use *https* or *http*, :: # svnlite checkout https://svn.freebsd.org/base/head /usr/src You may run into these errors: * svn: E120108: Error retrieving REPORT: The server unexpectedly closed the connection. * svn: E000054: Error retrieving REPORT: Connection reset by peer * svn: E120106: ra_serf: The server sent a truncated HTTP response body. I ran into these frequently. The only option I found was to try again and again with almost no success. :: # cd /usr/src # svnlite cleanup && TMP=/usr/home/raspberry/ svnlite up # TMP=/usr/home/raspberry/ svnlite checkout http://svn.freebsd.org/base/head /usr/src After trying the above for countless times and failing, another option was to use git instead of svnlite. I have not tested this myself. :: # pkg install git # cd /usr/src # svnlite cleanup # rm -rf ./* # rm -rf ./.svn # git svn init svn://svn.freebsd.org/base/head # git svn fetch -r294105 # git svn rebase At the time of writing HEAD was at revision 294105. In the above example, I chose to fetch svn history starting from the most recent revision. You should browse to `FreeBSD svn `_ to get the latest revision number. The reason is you want the initial download to not be too large by avoiding downloading complete svn history. `git svn rebase` is the equivalent of `svnlite update` so you'll be able to keep up with updates/revisions in future. More information from: * `very odd behaviour from svnlite on RPi2 `_ * `svn server problems `_ * `FreeBSD on Raspberry Pi - Getting the source `_ * `How do I force SVN to use /var/tmp NOT /tmp? `_ * `Is there a mercurial or git repository to download FreeBSD sources? `_ Build Toolchain +++++++++++++++++++++++ :: # chflags -R noschg /usr/obj/* # rm -rf /usr/obj # cd /usr/src # svnlite update Based on `freebsd-arm post by Andreas Schwarz `_ you may optionally want to disable debug files, expecially when like me you're using an 8GB storage card or you may find you have run out of disk space. :: # echo WITHOUT_DEBUG_FILES="YES" >> /etc/src.conf Create /etc/make.conf file ...:: # vim /etc/make.conf ...with these contents:: CC=clang CXX=clang++ CPP=clang-cpp WRKDIRPREFIX=/tmp WITH_PKGNG=yes I encountered an issue making buildworld and filed a `bug `_. Workaround is to make sure ``CPUTYPE?=native`` is **not** in */etc/make.conf*. Make buildworld (compiler toolchain). This will take a long time to run on RPi2 (about 36 hours on my machine). :: # make buildworld Build Kernel ++++++++++++++++++++++++ :: # cd /usr/src # make buildkernel Install Kernel ++++++++++++++++++++++++ :: # cd /usr/src # make installkernel Install World ++++++++++++++++++++++++ The handbook instructs to drop into single-user mode. :: # shutdown now Instead of showing a prompt the output "hung" and pressing enter did not yield a response. However, when I ran ctrl+alt+del the machine was rebooted. I found through a `mailing list `_ post that I need to have serial console access to proceed. This is where the USB to TTL serial console cable comes into play. Configure for Serial Console Access *********************************************** Download Mac OS X drivers from http://prolificusa.com/pl-2303hx-drivers/ and install them on your Mac. Reboot. Power off RPi2 and disconnect the power cable. DO NOT attach both the power cable and the serial cable simultaneously or your RPi2 will fry. Connect the USB-to-TTL cable to RPi2 following the `RPi2 GPIO docs `_. * Red end of the cable connects to RED pin on top left (see diagram in docs) * Leave the second RED pin empty * Black end connects to first BLACK pin on top row from the left (in the diagram) next to the empty red pin * White end connects to pin 14 * Green end connects to pin 15 Connect the USB end of the cable to the Mac's USB port. Use ``screen`` to connect to the serial console like so :: # ls -alhtr /dev/tty.* crw-rw-rw- 1 root wheel 18, 2 Dec 14 18:22 /dev/tty.Bluetooth-Modem crw-rw-rw- 1 root wheel 18, 0 Dec 14 18:22 /dev/tty.Bluetooth-Incoming-Port crw-rw-rw- 1 root wheel 18, 4 Dec 14 18:25 /dev/tty.usbserial # screen /dev/tty.usbserial 115200 You'll see the RPi2 booting up. Use Serial Console for Next Steps *********************************************** Login as *root* and then immediately go into single user mode. :: # shutdown now Shutdown NOW! shutdown: [pid 775] # *** FINAL System shutdown message from root@rpi2 *** System going down IMMEDIATELY System shutdown time has arrived Dec 15 02:23:50 rpi2 shutdown: shutdown by root: Stopping cron. Waiting for PIDS: 717. Stopping sshd. Waiting for PIDS: 713. Stopping powerd. Waiting for PIDS: 663. Stopping ntpd. Waiting for PIDS: 660. Stopping casperd. Waiting for PIDS: 607. Stopping rtsold. Stopping devd. Waiting for PIDS: 393. Writing entropy file:. Writing early boot entropy file:. . TerminaDec 15 02:23:54 rpi2 syslogd: exiting on signal 15 Enter full pathname of shell or RETURN for /bin/sh: # :: # adjkerntz -i # mergemaster -p # cd /usr/src # make installworld This will install new world and system binaries from /usr/obj and will take a long time to complete. Final Cleanup ++++++++++++++++++++++++ While still connected through the serial cable, complete the final cleanup. :: # cd /usr/src # mergemaster -iF # make delete-old # reboot After the reboot you may power off your RPi2, disconnect serial cable, and plug in the power cable. WiFi ------------------------------------------ I have the CanaKit WiFi dongle (CKXW1000). Inserting it and running ``ifconfig`` shows the driver (run0) it's using. :: root@rpi2:~ # ifconfig | grep -B3 -i wireless run0: flags=8802 metric 0 mtu 2290 ether de:de:de:22:22:22 media: IEEE 802.11 Wireless Ethernet autoselect (autoselect) Create or edit */etc/wpa_supplicant.conf* and add these lines. Change the SSID and PSK to match your enviornment. :: network={ ssid="myssid" psk="mypsk" } Add these lines to */etc/rc.conf* :: wlans_run0="wlan0" ifconfig_wlan0="WPA SYNCDHCP" Enable IPv6 SLAAC by adding this line to */etc/rc.conf* :: ifconfig_wlan0_ipv6="inet6 accept_rtadv" Restart network. :: root@rpi2:~ # service netif restart Note: I had better luck restarting the RPi, ``shutdown -r now`` ``kldstat`` had the following output :: root@rpi2:~ # kldstat Id Refs Address Size Name 1 20 0xc0100000 784e20 kernel 2 1 0xc42f2000 20000 if_run.ko 3 4 0xc4312000 51000 wlan.ko 4 1 0xc436d000 b000 firmware.ko 5 1 0xc438d000 b000 uhid.ko 6 1 0xc4261000 a000 wlan_wep.ko 7 1 0xc42cc000 b000 wlan_tkip.ko 8 1 0xc43c3000 e000 wlan_ccmp.ko Scan for available networks :: root@rpi2:~ # ifconfig wlan0 scan SSID/MESH ID BSSID CHAN RATE S:N INT CAPS HOME ff:ff:ff:3a:3a:3a 1 54M -31:-61 100 EP RSN HTCAP WPS WPA WME xfinitywifi d8:d8:d8:a9:a9:a9 6 54M -36:-67 100 ES HTCAP WME ATH myssid b5:b5:b5:c0:c0:c0 11 54M -21:-43 100 EPS RSN HTCAP WME Shell ------------------------------------------ In my image the default shell for the user was tcsh, even though the `documentation `_ states that it should be sh. To find your shell, run ``echo $SHELL``. Available Shells ++++++++++++++++++++++++++++++++++++++++++ To view a list of available shells, ``cat /etc/shells``. :: % cat /etc/shells # $FreeBSD: head/etc/shells 59717 2000-04-27 21:58:46Z ache $ # # List of acceptable shells for chpass(1). # Ftpd will not allow users to connect who are not using # one of these shells. /bin/sh /bin/csh /bin/tcsh Change Shell ++++++++++++++++++++++++++++++++++++++++++ To change your shell, use ``chsh``. You'll be prompted to enter your user's password. :: % /usr/bin/chsh -s /bin/sh Log out and log back in to see that you're using sh. :: $ echo $SHELL /bin/sh I'm trying to learn *tcsh* so sometimes I change my shell to use that. Whenever you see *$* prompt it means I'm using sh/bash, when you see *>* prompt it means I'm using tcsh. :: % /usr/bin/chsh -s /bin/tcsh For my daily driver I like to use *bash* :: # pkg install bash # echo "fdesc /dev/fd fdescfs rw 0 0" >> /etc/fstab # mount -t fdescfs fdesc /dev/fd $ /usr/bin/chsh -s /usr/local/bin/bash Set Environment Variables ------------------------------------------ There are some important environment variables (env vars) you'll want to either set for the first time or modify to suit your requirements. Since we changed the shell to sh in the previous step, we can use ``export`` to modify env vars. To view all env vars, use ``env``. :: $ env SSH_CLIENT= 62976 22 LOGNAME=raspberry PAGER= MAIL=/var/mail/raspberry PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/usr/home/raspberry/bin EDITOR= OLDPWD=/etc/defaults PWD=/usr/home/raspberry TERM=xterm-256color SSH_TTY=/dev/pts/0 HOME=/usr/home/raspberry USER=raspberry LC_COLLATE=C SSH_CONNECTION= 62976 22 SHELL=/bin/sh BLOCKSIZE=K EDITOR ++++++++++++++++++++++++++++++++++++++++++ Check what the EDITOR env var is currently set to, and you'll notice it's empty. :: $ echo $EDITOR Set this env var to use nano (installed earlier) to be the default editor of choice. :: $ export EDITOR="/usr/local/bin/vim" $ echo $EDITOR /usr/local/bin/vim PAGER ++++++++++++++++++++++++++++++++++++++++++ Check what the PAGER env var is currently set to, and you'll notice it's empty. :: $ echo $PAGER When it's not set the default pager is ``more``. I prefer to use ``less`` as my pager so I'll set it. :: $ export PAGER="/usr/bin/less" $ echo $PAGER /usr/bin/less Behavior of fn+delete ------------------------------------------ Mac Keyboard doesn't have a forward delete key the way generic keyboards do. Instead, the key combination fn+delete is used to do the same thing. This does not work as expected in csh or tcsh. Instead of forward deleting a character, a tilde (~) is printed. For example, in the text below, I typed fn+delete and got a tilde instead. :: % hel~o I found a solution on `Terminal on Mac - Delete key behavior `_. Use ``bindkey`` to map a sequence to *delete-char*. :: % bindkey "^[[3~" delete-char Now when you type fn+delete forward delete should work. To make it permanent, add the same command to *~/.cshrc* file. :: % echo 'bindkey "^[[3~" delete-char' >> ~/.cshrc Some useful resources: * `How do I get the backspace and forward delete keys to work correctly? `_ * `Fix backspace/delete when ssh'ing into Linux machines `_ * `Korn Shell: End, pgup, pgdown, and delete key not working `_ * `Re: delete key doesn't work with csh in xterm session `_ Command History in tcsh ------------------------------------------ It appears csh doesn't save history in a file to use across sessions. But tcsh does support the feature. Add these lines to your ~/.cshrc file. :: set history=2500 set savehist=5000 set histfile=~/.tcsh_history *history* stores commands for the current session. *savehistory* stores them across sessions. Thanks to `tofutim `_ for this tip. Command History in bash ------------------------------------------ Add these lines to your ~/.bash_profile file :: HISTFILESIZE=1500 HISTSIZE=750 HISTCONTROL=ignoreboth Then source the file to activate the settings. :: $ source ~/.bash_profile * `How do I keep my bash history across sessions? `_ * `histfile in csh `_ * `Bourne shell (/bin/sh) and Tcsh configuration `_ * `bash HISTSIZE vs. HISTFILESIZE? `_ * `How to: Unlimited Bash/shell history? `_ * `Shell initialization files `_ Firewall ------------------------------------------ I'll configure the pf (Packet Filter) firewall with a few rules. I found out about ``sysrc``, a tool to safely configure settings in */etc/rc.conf*. Instead of editing the file by hand I'll use that. To learn more about pf read `Firewalling with PF `_. To learn more about pf in FreeBSD read the `pf chapter `_ in the Handbook. Instead of me explaining all the tiny details of the rule set you should read the aforementioned resources. I'll add comments only to explain a tiny bit of what's going on. Enable pf in */etc/rc.conf* :: # sysrc pf_enable="YES" pf_enable: NO -> YES # sysrc pf_rules="/etc/pf.conf" pf_rules: /etc/pf.conf -> /etc/pf.conf # sysrc pflog_enable="YES" pflog_enable: NO -> YES # sysrc pflog_logfile="/var/log/pflog" pflog_logfile: /var/log/pflog -> /var/log/pflog Start pf without configuring any rules. You'll see a warning because */etc/pf.conf* does not exist but it can be ignored for now. :: # service pf start /etc/rc.d/pf: WARNING: /etc/pf.conf is not readable. # service pflog start Starting pflog. Create these rules in */etc/pf.conf* :: ext_if = "ue0" localnet = "{ self }" # add any /64 subnet(s) you have configured on your network # just for fun I don't allow SSH over IPv4 adminnet = "{ fc00::/7, fe80::/10 }" # edit the list to exclude your internal network otherwise you may not be able to SSH in martians = "{,,,,,,, }" client_out = "{ ssh, domain, nntp, http, https }" admin_services = "{ ssh }" udp_services = "{ domain, ntp }" icmp_types = "{ echoreq, unreach }" http_servers = "{ }" http6_servers = "{ 2604:a880:1:20::fa:4001 }" # could use *drop* instead of *return* to provide no feedback set block-policy return match in all scrub (no-df max-mss 1440) antispoof for $ext_if block all set skip on {lo0} block drop in quick on $ext_if from $martians to any block drop out quick on $ext_if from any to $martians pass quick inet proto { tcp, udp } to port $udp_services keep state # allow ping and MTU path discovery pass inet proto icmp all icmp-type $icmp_types # allow outbound traceroute pass out on $ext_if inet proto udp to port 33433 >< 33626 # only allow ingress SSH over IPv6 from a specific subnet pass in inet6 proto tcp from $adminnet to any port $admin_services # # IPv6 related rules # pass out on $ext_if inet6 proto icmp6 all icmp6-type echoreq keep state pass out on $ext_if inet6 proto icmp6 all icmp6-type {neighbradv, neighbrsol} # ND advertisement in pass in on $ext_if inet6 proto icmp6 all icmp6-type {neighbradv, neighbrsol} # Router advertisement out pass out on $ext_if inet6 proto icmp6 all icmp6-type routeradv # Router solicitation in pass in on $ext_if inet6 proto icmp6 all icmp6-type routersol Now enable these rules using the ``pfctl`` command :: # pfctl -f /etc/pf.conf Use ``tcpdump`` to read pf logs. Thanks to `how to read pflog logs? `_ for the tip. :: # tcpdump -netttr /var/log/pflog Jails ------------------------------------------ TODO bhyve ------------------------------------------ TODO nginx ------------------------------------------ Install nginx and enable it :: # pkg update # pkg install nginx # sysrc nginx_enable="YES" Configure nginx. :: # vim /usr/local/etc/nginx/nginx.conf Leave everything as is, except the following. Comment out `server` directives as well. :: user www www; worker_processes 4; error_log logs/error.log info; pid logs/nginx.pid; events { worker_connections 1024; } http { ... include /usr/local/etc/nginx/conf.d/*.conf; ... #server { # ... #} ... } Create an example server config (edit it as you like) :: # mkdir -p /usr/local/etc/nginx/conf.d/ # vim /usr/local/etc/nginx/conf.d/example_com.conf The config should look something like this. :: server { listen default_server; listen [2601::abab:abff:fe01:0101]:80 default_server; listen [fd85::abab:abff:fe01:0101]:80 default_server; server_name .example.com ""; root /var/www/example.com; index index.html index.htm; location / { # First attempt to serve request as file, then # as directory, then fall back to displaying a 404. try_files $uri $uri/ =404; # Uncomment to enable naxsi on this location # include /etc/nginx/naxsi.rules } } Create directory for logs :: # mkdir -p /usr/local/etc/nginx/logs/ # chown www:www /usr/local/etc/nginx/logs/ Create directories to place the website's files. :: # mkdir -p /var/www/example.com # chown raspberry:www /var/www/example.com # chmod 755 /var/www/example.com Verify the nginx config is valid. :: # nginx -t You may see the following error but you can safely ignore it. It's documented at `nginx error after upgrading `_. You just need to restart nginx to make this error go away. Do not ignore other errors, though. :: nginx: [emerg] mkdir() "/var/tmp/nginx/client_body_temp" failed (2: No such file or directory) Restart nginx. :: # service nginx restart Certificate Authority ------------------------------------------ TODO OpenVPN ------------------------------------------ TODO Router ------------------------------------------ TODO Transparent Tor Proxy ------------------------------------------ TODO * `Tor Transparent Proxy on FreeBSD `_ * `[HOWTO] use Tor network and web proxy `_ * `OpenWRT Tor transparent proxy+bridge `_ Poudriere ------------------------------------------ TODO: Build packages on Digital Ocean for rpi2