Eric Radman : a Journal

Run Your Own Server

Configuring your own box on the Internet is a lot of fun, and provides an opportunity to experiment with Internet services in general.

Service Cost Provider
Domain registration $11/yr.
OpenBSD VPS hosting $10/mo. (based on resources used)
Secondary DNS $10/yr. (donation)

VPS Hosting

Initial Setup

Getting started with a service like is easy, after you select a plan and enter your data an e-mail will be sent with your initial login information. First login and change your login credentials.

ssh sshadmin@
useradd -m eradman
vi /etc/group
userdel sshadmin
rm -rf /home/sshadmin

Out of the gate you may also want to prevent password authentication for anyone not in the weel group.

# Require keys for regular users
Match Group !wheel
    PasswordAuthentication no

Then set the hostname and timezone

echo "" > /etc/myname
ln -sf /usr/share/zoneinfo/America/New_York /etc/localtime

If you ever need to repair your install your hosting provider should be able to give you access via VNC. To increase your odds of recovering the system enable keyboard reset in case you can't log on and need to single user mode:

machdep.kbdreset=1 # permit console CTRL-ALT-DEL to do a nice halt

If you botch an upgrade booting off of the install boot image (bsd.rd) will also give you a fully functional environment to make repairs from.

Now is also a good time to disable root logins

PermitRootLogin no

Services - HTTP

chown eradman:users /var/www/htdocs
rm /var/www/htdocs/*


If you like Nginx that's easy as well

http {
    access_log   /var/www/logs/access.log main;
    gzip  on;
    index index.html;

    server {
        location /posts {
            autoindex on;

Nginx provides an easy way to exclude some content from it's web logs which saves on a lot of space an noise.

    server {
        location ~* \.(css|png|js|ico)$ {
            access_log off;
            expires max;

Services - DNS

Since 5.4 OpenBSD ships with NSD by default. If you were using BIND the zone format is idential, you only need to enable it and add the list of zones to nsd.conf.

echo 'nsd_flags=""' >> /etc/rc.conf.local

Primary Nameserver

        name: ""
        zonefile: ""
$TTL 6h

    2     ; serial
    1h    ; refresh
    30m   ; retry
    7d    ; expiration
    1h )  ; minimum

www     IN  CNAME
vm      IN  CNAME

After restarting nsd verify like so

$ host has address mail is handled by 50

Secondary Nameservers

There are two rules to running your own nameserver

  1. There must be at least two
  2. They must not have the same IP address

All registrars that I'm aware have an awkward JavaScript-only user interface, but I recommend because they provide very quick e-mail support.

This is why a secondary nameservice is required , and provides an excellent solution. Once you create an account update your nameserver config to answer client queries so that they can keep the nameservers in sync.

    # ...
    provide-xfr: NOKEY
    provide-xfr: NOKEY
    provide-xfr: 2607:f0d0:1005:72::100 NOKEY
    provide-xfr: 2a01:4f8:d12:d01::10:100 NOKEY

Next add them as secondary authority for each zone file.



Once this works locally, use a DNS health check such as to verify that your configuration is correct.


First write your hosting provider and ask them to add a PTR record for your IP address, then add an MX record for your domain


                MX      50
selector1._domainkey IN TXT "k=rsa; t=s; p=MIGf...o8P2

Then stop sendmail and enable smtpd by following the instructions in the smtpd(8) man page.

Confirm that local relays are working by tailing /var/log/maillog or by running smtpd in the foreground with -dv

Now proceed to create rules in /etc/mail/smtpd.conf for virtual domains and SMTP relay

pki certificate "/etc/ssl/"
pki key "/etc/ssl/private/"

listen on lo0 port 25
listen on egress port 25
listen on egress port 465 smtps pki auth

table aliases db:/etc/mail/aliases.db
accept from any for domain "" deliver to mbox
accept for local alias <aliases> deliver to mbox

OpenSMTPD supports SSL/TLS and STARTTLS modes using the keyword https (normally port

465), and tls (normally port 587). Both of these protocols are SSL connections, but the latter switches to secure mode after connecting. If the client sends a username and password the connection is considered local and passes the last rule, allowing relay. The smtpd.conf(5) mage page suggests a means of generating your own certificate.

Gmail specifically demands that messages be signed with a public key that matches the _domainkey TXT record for the domain. OpenSMTPD allows you to route messages through DKIMproxy in order to sign each e-mail:

listen on lo0 port 10028 tag DKIM
accept tagged DKIM for any relay
accept from local for any relay via smtp://

A competing or complementary technology for validating sender identity is SPF. This is much easer to configure it's simply a record that is used to specify which hosts are permitted to relay mail for a given domain. easySPF is one of several handy tools for generating these records. The final nameserver entries for DKIM and SPF have this form

selector1._domainkey IN TXT "k=rsa; t=s; p=MIGf...o8P2
                     IN TXT "v=spf1 mx a ptr ip4: ~all"

I also recommend fighting off spam by following the instructions at to set up greylisting using BGP to distribute OpenBSD spamd lists.

There are two services that were brought to my attention that can verify the SPF and DKIM signatures of a mail server. Simply send a message to and a report will be mailed back. mxtoolbox also provides a web-based diagnostic tool.

Other systems that are permitted to relay mail can simply add a relay via rule to their smtpd configuration

accept for any relay via "smtp://"

Mail Retrieval over SSL

By far the easiest way to configure pop3 access is using pop3d, soon to be available from ports under mail/pop3d. It's a zero-configuration daemon, I only block the plain text port:

block in on ! lo0 proto tcp to port pop3


Now that everything is in working order set up a small script to make a copy of each file system.

df -h
/sbin/dump -0af - /home | ssh $host "cat > /vm/"
/sbin/dump -0af - /var  | ssh $host "cat > /vm/"
/sbin/dump -0af - /     | ssh $host "cat > /vm/"

See also Why's and When's of Backup and Restore by Gerhard Mourani for more information about backup levels and rotation.

Preventing an Attack

If you allow Windows clients to authenticate against your server then it is also prudent to block activity that indicates that the PC has been hijacked. The following will add a client to a blacklist if there are more than 2 concurrent connections to port 465, or there are more than 8 connections made over a 30-second window:

table <attacker> persist
block quick from <attacker>
pass inet proto tcp to egress:network port smtps keep state \
      (max-src-conn 2, max-src-conn-rate 8/30, overload <attacker>)

A daily cron job to list such connections is as easy as

00      1       *       *       *       /sbin/pfctl -t attacker -T show

Or a PF table can be given an expiration date for it's entries. Here we block all such hosts for 3 days:

/sbin/pfctl -t attacker -T expire 259200

See Peter Hansteen's PF tutorial provides for a more complete explanation of these tactics.

Last updated on November 26, 2016