<!--order=1-->


<h1>OpenBSD First Boot Checklist</h1>
<p>OpenBSD rewards a deliberate first hour. The base system is small, the defaults are conservative, and the tools are consistent — but a machine is not ready for unattended work just because it finished installing. This is the checklist I use before treating an OpenBSD host as a useful server, gateway, or field machine.</p>

<h2>Confirm What You Installed</h2>
<p>Before changing anything, record the release and hardware. It makes later troubleshooting much easier, especially when a driver or package behaves differently between releases:</p>
<pre>
$ uname -a
$ hostname
$ dmesg | less
$ sysctl kern.version
</pre>
<p>Write down the hostname, network interface names, disk layout, installation media, and the purpose of the machine. A short deployment note is often more useful than trying to reconstruct the setup months later.</p>

<h2>Create an Administrative Account</h2>
<p>Do not make routine SSH work depend on a direct root login. Create a named account, put it in the <code>wheel</code> group, and use OpenBSD's built-in <code>doas</code> for the occasional privileged command:</p>
<pre>
# Run these as root. adduser is interactive.
# adduser
# usermod -G wheel jason

# /etc/doas.conf
permit :wheel
</pre>
<p>Replace <code>jason</code> with the real account name. Keep the <code>doas.conf</code> rule simple at first. Once the account works, test <code>doas</code> from a second session before closing the root console.</p>

<h2>Install Your SSH Key Before Hardening SSH</h2>
<p>Use a key that is already backed up on your workstation. On the workstation, generate an Ed25519 key if you do not have one:</p>
<pre>
$ ssh-keygen -t ed25519 -C "jason@workstation"
</pre>
<p>For the first connection, copy the public key into the new account's <code>authorized_keys</code>. When a convenience command is not available on the workstation, the manual method works everywhere:</p>
<pre>
$ ssh jason@openbsd-host
$ mkdir -p ~/.ssh
$ chmod 700 ~/.ssh
$ vi ~/.ssh/authorized_keys
$ chmod 600 ~/.ssh/authorized_keys
</pre>
<p>Paste the contents of the workstation's <code>id_ed25519.pub</code> into that file. Open a second terminal and confirm that key login works before disabling password login.</p>

<h2>Harden and Validate sshd</h2>
<p>Edit <code>/etc/ssh/sshd_config</code> only after key authentication has been tested. The exact policy depends on how the machine is managed, but these are sensible starting points for an internet-facing host:</p>
<pre>
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
</pre>
<p>If more than one person needs access, prefer an explicit <code>AllowUsers</code> or <code>AllowGroups</code> policy over sharing an account. Keep the second session open while validating the change:</p>
<pre>
# Check syntax before reloading.
# sshd -t

# Reload without unnecessarily dropping existing sessions.
# rcctl reload sshd
</pre>
<p>Do not turn off password authentication until you have a working key, a tested <code>doas</code> account, and a recovery path through the local console or out-of-band management.</p>

<h2>Apply OpenBSD Updates</h2>
<p>OpenBSD separates release upgrades from errata patches. Keep the installed release current with <code>syspatch</code>, and use <code>sysupgrade</code> deliberately when moving to a newer release. Packages are updated separately:</p>
<pre>
# Install the published binary errata for the current release.
# syspatch

# Review and update installed packages.
# pkg_add -u

# Inspect package and patch state.
# syspatch -l
# pkg_info
</pre>
<p>Read the release notes and upgrade documentation before using <code>sysupgrade</code>. A major or release upgrade is a maintenance event: make a backup, confirm console access, record third-party packages, and do not combine it with unrelated application changes.</p>

<h2>Know Which Services Are Enabled</h2>
<p>OpenBSD uses <code>rcctl</code> for service management. Check what is enabled rather than assuming an installed daemon is running:</p>
<pre>
# List services enabled at boot.
# rcctl ls on

# See available service names and current state.
# rcctl ls all
# rcctl status sshd

# Enable a service only when the machine needs it.
# rcctl enable ntpd
# rcctl start ntpd
</pre>
<p>Every extra listening service is another decision to document and maintain. On a small host, a short list of enabled daemons is usually a feature.</p>

<h2>Check the Network Before You Leave the Console</h2>
<pre>
# Replace em0 with the interface shown by dmesg or ifconfig.
$ ifconfig
$ route -n show
$ ping -c 3 192.0.2.1
$ ping -c 3 9.9.9.9
$ ping -c 3 openbsd.org
</pre>
<p>Test the local gateway, an address outside the local network, and DNS separately. If the first failure is DNS, there is no point debugging the firewall yet. Save the final interface and hostname configuration in the deployment notes.</p>

<h2>Enable Only the Firewall Policy You Understand</h2>
<p>OpenBSD's <code>pf</code> is powerful enough to lock you out with one careless rule. The companion article <a href="categories.php?cat=Firewalls&amp;article=Deep%20Dive%20into%20OpenBSD%27s%20%60pf%60%20Firewall">OpenBSD pf — The Packet Filter</a> covers rule structure, tables, validation, and state handling. Start with a policy that describes the services you actually need, validate it, and keep a console or second session available while loading it:</p>
<pre>
# Validate without loading the ruleset.
# pfctl -nf /etc/pf.conf

# Inspect the active rules and states.
# pfctl -sr
# pfctl -ss
</pre>
<p>Do not paste a generic “deny everything” ruleset onto a remote machine without first allowing your administration path and confirming the interface names. Firewall changes should be reversible from the console.</p>

<h2>Make a Small Maintenance Record</h2>
<p>Before calling the host finished, record:</p>
<ul>
  <li>hostname, purpose, location, and responsible person</li>
  <li>release, architecture, disk layout, and network interfaces</li>
  <li>enabled services and the ports they expose</li>
  <li>where backups live and how console recovery works</li>
  <li>the last successful <code>syspatch</code>, package update, and restore test</li>
</ul>
<p>The best OpenBSD setup is not the one with the most hardening pasted into a configuration file. It is the one whose owner knows what is running, can update it safely, and can recover it when the network or storage does something unexpected.</p>

<h2>References</h2>
<ul>
  <li><a href="https://www.openbsd.org/faq/faq4.html" target="_blank" rel="noopener">OpenBSD FAQ — Installation and Setup ↗</a></li>
  <li><a href="https://www.openbsd.org/faq/faq10.html" target="_blank" rel="noopener">OpenBSD FAQ — System Maintenance ↗</a></li>
  <li><a href="https://man.openbsd.org/" target="_blank" rel="noopener">OpenBSD manual pages ↗</a></li>
  <li><a href="https://www.openbsd.org/faq/pf/" target="_blank" rel="noopener">OpenBSD PF User's Guide ↗</a></li>
</ul>