I have been using Linux for many years, but only recently found out about /etc/motd. When you SSH into a server, it displays a message that varies depending on your Linux distribution. For instance, a stock Debian installation looks like this:

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Wed Sep 14 23:38:34 2016
[email protected]:~#

I never thought to look at where this message comes from, but apparently it lives in /etc/motd. I believe this stands for “message of the day”. This means that you can have this message say anything that you would like by editing the contents of /etc/motd.

For example, you can use this Text to ASCII generator to put the hostname of your server in stunning ASCII text and make it look like this:

Levs-MacBook-Pro:~ levlaz$  ssh dev.levops.net
     _            _                                        _
  __| | _____   _| | _____   _____  _ __  ___   _ __   ___| |_
 / _` |/ _ \ \ / / |/ _ \ \ / / _ \| '_ \/ __| | '_ \ / _ \ __|
| (_| |  __/\ V /| |  __/\ V / (_) | |_) \__ \_| | | |  __/ |_
 \__,_|\___| \_(_)_|\___| \_/ \___/| .__/|___(_)_| |_|\___|\__|


This is pretty neat! You can also do some fancy things like Ubuntu does and make this message change depending on various events such as security updates being available or a server restart being required. You can explore the scripts that Ubuntu uses in the /etc/update-motd.d/ directory on a standard install.

Alpine Linux, wget, and ca-certificates

I’ve been working with Alpine Linux this week. This tiny Linux distribution is an excellent choice for a base docker image or, in my case, for a low power VPS. I love how easy and fast it is to install and configure this distribution.

One stumbling block that I ran into was downloading random things from the internet with wget.

Unable to locally verify the issuer's authority.
To connect to dl.eff.org insecurely, use `--no-check-certificate'

I saw this timely tweet by Joe Gross the other day and decided that rather than ignoring the error messages that wget was throwing I would go and figure out what was wrong.

It turns out that when you make an 83MB distribution you need to cut some of the fat. The ca-certificates package that is common in every Linux Distribution under the sun is missing from the default installation of Alpine.

In order to resolve the angry warnings from wget, you can install the ca-certificates package with the following command:

apk -U add ca-certificates

This will make wget happy, and your server secure. In case you are wondering, skipping this step and running wget with --no-check-certificate totally works. However, it is also inviting a man in the middle attack. Don’t ever do this.

I Inherited an Open Source Project

Last week I was browsing Twitter when I noticed a retweet where Honza was putting all of his open source projects up for adoption since he is going to go work at Apple. I took a look at the long list of neat projects that were up for adoption and decided to throw my hat in the ring for Pong.

Pong is a simple self-hosted server monitoring tool written in Swift. I have been increasingly interested in server side swift so this is a great opportunity to dive in a learn some more.

I don’t have any major plans for this project right now other than being a good steward and a responsive maintainer. If you have some ideas of things that you would like to see please let me know!

Vim is Awesome

I have been meaning to post this for quite some time, but there is this fantastic website called Vim Awesome that has an exhaustive list of vim plugins along with their respective docs and installation instructions. It is a great way to learn more about all of the wonderful plugins that take vim to the next level.

Vim is awesome in its very own right, but it is powerful plugins like Vim Fugitive that really make it shine in my opinion.

If you are new to vim, or even a veteran who has never really messed around with plugins, I would highly recommend checking out this great resource. As a side note, I would also recommend using Vundle since it makes managing your vim plugins across multiple machines super simple.

Recovering from Syntax Errors in /etc/rc.conf in FreeBSD

I have been exploring FreeBSD over the last few weeks. In fact, I moved this blog over to a server running FreeBSD tonight. Naturally, while fiddling around with /etc/rc.conf (the default init file of FreeBSD) with vi I made a syntax error. Upon rebooting, FreeBSD yells at me and starts a shell in a read only file system.

Loading configuration files.
/etc/rc.conf: 16: Syntax error: Unterminated quoted string
Enter full pathname of shell or RETURN for /bin/sh:

At first, I was super sad and thought I had to reinstall everything (which would not have been so bad since the installation just takes a few minutes), but then I realized that it is not possible that I am the first person to ever make an error in this file, there has to be a way to recover. Sure enough, there is.

  1. Remount the Root File System

    First we must remount the root files system. Go ahead and press RETURN to pop into /bin/sh

    /sbin/mount -o rw /
  2. Edit /etc/rc.conf

    Now that we have a read/write file system mounted we can edit our /etc/rc.conf file and fix the syntax error using vi

  3. Reboot

    Reboot, and FreeBSD will be back in action.

Working with chruby and nvm on Ubuntu

I am setting up a new Ubuntu 16.04 dev environment. I wanted to take some notes on my progress. I am trying out chruby after it being highly recommended by the ruby gurus Eric and Zach. A natural place to start would be to get this Jekyll blog running locally. I ran into a few stumbling blocks.

Installing chruby and a Ruby version

There are many different ways to do this, I chose the method below.

  1. Download and Install chruby
    wget -O chruby-0.3.9.tar.gz https://github.com/postmodern/chruby/archive/v0.3.9.tar.gz
    tar xf chruby-0.3.9.tar.gz
    cd chruby-0.3.9/
    sudo make install
  2. Add chruby to your .bashrc
    source /usr/local/share/chruby/chruby.sh
    source /usr/local/share/chruby/auto.sh
  3. Install dependencies
    sudo apt-get install -y build-essential bison zlib1g-dev \
    libyaml-dev libssl-dev libgdbm-dev libreadline-dev \
    libncurses5-dev libffi-dev
  4. Install Ruby 2.3.1

    This will work for any version of Ruby, but 2.3.1 is the one that I needed.

    wget http://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.1.tar.bz2
    tar xf ruby-2.3.1.tar.bz2
    cd ruby-2.3.1/
    ./configure --prefix=/opt/rubies/ruby-2.3.1
    sudo make install
  5. Install Gems for Jekyll

    Now that we have Ruby installed, we can install bundler and install all of our Gems.

    chruby 2.3.1
    gem install bundle
    bundle install

Once everything had been installed I tried to start up jekyll, and of course it did not work since I do not yet have node installed.

`rescue in block (2 levels) in require': There was an error while trying to load
the gem 'jekyll-coffeescript'. (Bundler::GemRequireError)
Gem Load Error is: Could not find a JavaScript runtime. See
https://github.com/rails/execjs for a list of available runtimes.

Since I often work with many different versions of node, I took the opportunity to install nvm rather than the version of node that is available in the Ubuntu repositories.

Installing nvm

nvm is a really nice tool for working with various versions of node.

  1. Run the installer script
    curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.7/install.sh | bash

    This will install nvm and add the appropriate lines to your ~/.bashrc file in order to load properly.

  2. Install the latest version of node

    nvm install node
  3. Source NVM

    To get nvm working in the same terminal, you can run source ~/.bashrc, alternatively you can open a new terminal and nvm will automatically be sourced since the installer script added the appropriate bits for us.

You can now load jekyll with jekyll -s. Not only do we have Jekyll running like a charm, we also are ready to work with any version of Ruby or Node with chruby and nvm.

Installing Slack on Ubuntu

Ah Slack, the email killer, the bane of my existence. Now in stunning Ubuntu 3d. Like chrome before it, and seemingly all electron apps, the .deb is not able to resolve all dependencies. In order to get slack working you must do the following.

  1. Download the latest .deb from here

  2. Try to install the .deb with dpkg

    cd ~/Downloads
    sudo dpkg -i slack-desktop-*-amd64.deb

    This step will fail with an error that looks like this:

    [email protected]:~/Downloads$ sudo dpkg -i slack-desktop-2.1.2-amd64.deb
    Selecting previously unselected package slack-desktop.
    (Reading database ... 228971 files and directories currently installed.)
    Preparing to unpack slack-desktop-2.1.2-amd64.deb ...
    Unpacking slack-desktop (2.1.2) ...
    dpkg: dependency problems prevent configuration of slack-desktop:
    slack-desktop depends on libappindicator1; however:
    Package libappindicator1 is not installed.
    dpkg: error processing package slack-desktop (--install):
    dependency problems - leaving unconfigured
    Processing triggers for gnome-menus (3.13.3-6ubuntu3.1) ...
    Processing triggers for desktop-file-utils (0.22-1ubuntu5) ...
    Processing triggers for bamfdaemon (0.5.3~bzr0+16.04.20160701-0ubuntu1) ...
    Rebuilding /usr/share/applications/bamf-2.index...
    Processing triggers for mime-support (3.59ubuntu1) ...
    Errors were encountered while processing:
  3. Once that step fails, install the required dependencies with
    sudo apt-get -f install

Now you can open Slack and chat away.

Installing Nextcloud on a FreeBSD VPS


Nextcloud is an exciting new fork of OwnCloud. I have been meaning to try it out lately and I finally got around to doing it. I picked Vultr for this instance since they have really affordable “Spinny Disk” instances starting at just $5/mo for 125GB. The performance is noticeably slower than SSD, but if you are looking for a low cost place to store all of your files then this deal cannot be beat. Vultr also comes with full support for FreeBSD out of the box, which is a great choice for a system like this.

The official Nextcloud documentation is wonderful, however it seems like it geared toward large multi-user installs. The purpose of this guide is to make it easy to install Nextcloud for a single (or just a few) user system. If you follow this guide you will have the latest stable version of Nextcloud with PHP7, Apache 2.4, MySQL 5.7 and Redis secured with LetsEncrypt on the latest stable version of FreeBSD.

Pre Requisites

In order to complete this guide successfully with a TLS enabled Nextcloud site you must have a domain name with DNS that successfully resolves to the IP address of your VPS Server.

Configuration Steps

  1. Launch a new Storage Instance in the DC of your choice. In my specific case I am running a 512MB RAM/125GB HD instance in the Los Angeles Data Center.
  2. SSH into the new VPS.
  3. Update and Upgrade BSD
    pkg update && pkg upgrade
    # [Optional] Install some helper packages
    pkg install vim-lite htop tmux
  4. Add some swap

    By default, the storage instance does not come with a swap partition, since I chose the smallest instance with 512MB of RAM, it is probably a good idea to add some swap because if the system ever runs out of memory the whole entire thing will come crashing down.

    You can read more about how to add swap in FreeBSD, but the gist of it is:

    # Create a 1GB sawp file
    dd if=/dev/zero of=/swap bs=1m count=1024
    # Set proper permissions on swap file
    chmod 600 /swap
    # Add swap to /etc/fstab
    md99    none    swap    sw,file=/swap,late  0   0
    # Turn swap on
    swapon -aL

    If everything was successful, running htop you should now see some swap space.

  5. Install and Configure BAMP Stack (BSD, Apache, MySQL, PHP) and Redis

    • Install all packages and dependencies
      pkg install apache24 mysql57-server redis php70 mod_php70 php70-pdo_mysql \
      php70-redis php70-gd php70-curl php70-json php70-zip php70-dom \
      php70-xmlwriter php70-xmlreader php70-xml php70-mbstring php70-ctype \
      php70-zlib php70-simplexml php70-hash php70-fileinfo php70-posix \
      php70-iconv php70-filter php70-openssl
    • Add Services to /etc/rc.conf
      # /etc/rc.conf
    • Configure Apache

      Ensure that the rewrite and ssl modules are enabled (uncommented) in /usr/local/etc/apache24/httpd.conf.

      # /usr/local/etc/apache24/httpd.conf
      LoadModule ssl_module libexec/apache24/mod_ssl.so
      LoadModule rewrite_module libexec/apache24/mod_rewrite.so

      Add a PHP handler to /usr/local/etc/apache24/modules.d

      # /usr/local/etc/apache24/modules.d/001_mod_php.conf
      <FilesMatch "\.php$">
      SetHandler application/x-httpd-php
      <FilesMatch "\.phps$">
      SetHandler application/x-httpd-php-source
    • Configure MySQL

      Once MySQL has been added to /etc/rc.conf you can start it up by executing the following command in your shell:

      /usr/local/etc/rc.d/mysql-server start

      The first time MySQL runs it will create a root password which can be found in $HOME/.mysql_secret, use this password to log into MySQL, change the root password, and then create a new admin user for Nextcloud.

      # Grab the Root Password
      cat ~/.mysql-secret
      # Log into MySQL
      mysql -u root -p $PASSWORD # Password from previous step
      # Change the Root Password
      ALTER USER 'root'@'localhost' IDENTIFIED BY '$NEW_PASSWORD';
      # Create New Schema for Nextcloud
      CREATE DATABASE nextcloud;
      # Create New Admin User for Nextcloud
      CREATE USER 'nextcloud_admin'@'localhost' IDENTIFIED BY '$OTHER_NEW_PASSWORD';
      # Grant Permissions to the new Admin user to the Nextcloud Schema
      GRANT ALL ON nextcloud.* TO 'nextcloud_admin'@'localhost';
      # Refresh all Privileges
    • Configure Redis

      There are many different memory caching strategies for Nextcloud. I like using Redis for this sort of thing, you can chose whichever strategy you prefer.

      The following (optional) configuration will make redis run on a local socket instead of over TCP. This is better from a security perspective.

      Update /usr/local/etc/redis.conf to run on local socket

      # /usr/local/etc/redis.conf
      port 0
      unixsocket /tmp/redis.sock
      unixsocketperm 750

      Add www user to the wheel group so that it has permission to access this socket.

      pw groupmod wheel -m www

      Start Redis

      /usr/local/etc/rc.d/redis start

      If everything went well, you should see the redis socket in /tmp

      # ls -al /tmp
      total 48
      drwxrwxrwt   7 root   wheel  512 Sep  1 23:02 .
      drwxr-xr-x  18 root   wheel  512 Sep  1 22:03 ..
      srwxr-x---   1 redis  wheel    0 Sep  1 23:02 redis.sock
  6. Download Nextcloud

    We are almost there! The last few steps are to actually download and configure Nextcloud. You can get the latest version of Nextcloud from here.

    # Go to the default apache data directory
    cd /usr/local/www/apache24/data
    # Download Nextcloud
    wget https://download.nextcloud.com/server/releases/nextcloud-10.0.0.zip
    # Unzip Nextcloud
    unzip nextcloud-10.0.0.zip
    # Make sure the www user owns this directory
    chown -R www:www nextcloud
  7. Install and run certbot by LetsEncrypt

    The full instructions are available here but the gist is:

    # Install the Package
    pkg install py27-certbot
    # Generate the Cert
    certbot certonly

    Go through the certbot UI and fill out your site specific details. If all goes well you should see a message that says:

    Congratulations! Your certificate and chain have been saved at /usr/local/etc/letsencrypt/live/$YOUR_SITE/fullchain.pem

  8. Create a VirtualHost Configuration for Nextcloud

    Create a new file called $YOUR_SITE.conf in /usr/local/etc/apache24/Includes, the contents of this file should have a VirtualHost specification for your new Nextcloud site.

    The first VirtualHost will listen on port 80 and redirect all requests to HTTPS. The second VirtualHost will listen on port 443 and serve your actual Nextcloud site.

    <VirtualHost *:80>
      ServerAdmin $YOUR_EMAIL
      ServerName $YOUR_SITE
      RewriteEngine on
      RewriteCond %{SERVER_NAME} =$YOUR_SITE
      RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,QSA,R=permanent]
    Listen 443
    <IfModule mod_ssl.c>
      <VirtualHost *:443>
        ServerAdmin $YOUR_EMAIL
        ServerName $YOUR_SITE
        DirectoryIndex index.php
        DocumentRoot /usr/local/www/apache24/data/nextcloud
        SSLCertificateFile /usr/local/etc/letsencrypt/live/$YOUR_SITE/fullchain.pem
        SSLCertificateKeyFile /usr/local/etc/letsencrypt/live/$YOUR_SITE/privkey.pem
        SSLEngine on
        # Intermediate configuration, tweak to your needs
        SSLProtocol             all -SSLv2 -SSLv3
        SSLHonorCipherOrder     on
        SSLCompression          off
        SSLOptions +StrictRequire
        <Directory /usr/local/www/apache24/data/nextcloud>
          AllowOverride all
        <IfModule mod_headers.c>
          Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains"

    Start apache with /usr/local/etc/rc.d/apache24 start

  9. Configure Nextcloud

    • Verify Installation

      Go to http://$YOUR_SITE.com, verify that you get redirected to HTTPS and that the certificate shows up as valid.

    • Create Admin Account

      If this page loads properly, you should create an admin user, set the data directory location, and fill in the database credentials from step 5.

    • Tweak Config File

      We need to tweak the config file in order to enable Redis memory caching. Open up /usr/local/www/apache24/data/nextcloud/config/config.php and add:

      # /usr/local/www/apache24/data/nextcloud/config/config.php
      'memcache.locking' => '\\OC\\Memcache\\Redis',
      'memcache.local' => '\\OC\\Memcache\\Redis',
      'redis' =>
      array (
      'host' => '/tmp/redis.sock',
      'port' => 0,
    • Use System Cron Job

      By default NextCloud uses an AJAX cron, the performance is a bit better if you let the system cron handle this. Add the following to the crontab:

      # crontab -u www-data -e
      */15  *  *  *  * php -f /usr/local/www/apache24/data/nextcloud/cron.php

      Once this has been added, select Cron from Admin -> Settings

    • Enjoy Nextcloud

      That was a lot of steps, but now we have a private, self hosted, secure, and affordable Nextcloud instance. If you ran into any issues during installation please let me know in the comments below!

Next Steps