{"id":165027,"date":"2026-03-29T12:11:19","date_gmt":"2026-03-29T09:11:19","guid":{"rendered":"https:\/\/computingforgeeks.com\/void-linux-post-install-setup\/"},"modified":"2026-03-29T21:17:14","modified_gmt":"2026-03-29T18:17:14","slug":"void-linux-post-install-setup","status":"publish","type":"post","link":"https:\/\/computingforgeeks.com\/void-linux-post-install-setup\/","title":{"rendered":"Void Linux Post-Installation Setup Guide"},"content":{"rendered":"\n<p>A fresh Void Linux install is minimal by design. You get a bootable system, a shell, and not much else. That&#8217;s the point. But between a bare install and a usable workstation or server, there&#8217;s a gap that needs filling: logging, firewall rules, a proper editor, time sync, and a user account that isn&#8217;t root.<\/p>\n\n\n\n<p>This guide walks through the essential post-installation steps for Void Linux (glibc, x86_64). Everything here was tested on a clean install with the base system image. If you&#8217;re coming from a systemd-based distro like Fedora or Ubuntu, pay close attention to the runit and XBPS sections because Void does things differently, and the differences matter. For a deeper reference, the <a href=\"https:\/\/docs.voidlinux.org\/\" target=\"_blank\" rel=\"noreferrer noopener\">Void Linux Handbook<\/a> covers the full picture.<\/p>\n\n\n\n<p><em>Verified working: <strong>March 2026<\/strong> on Void Linux x86_64 (glibc), kernel 6.x<\/em><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Update the System<\/h2>\n\n\n\n<p>Before installing anything, bring the system up to date. Void uses XBPS (X Binary Package System), and there&#8217;s a quirk worth knowing: the package manager itself needs to be updated before you update everything else. If xbps is outdated, it may not handle newer package metadata correctly.<\/p>\n\n\n\n<p>Update xbps first:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo xbps-install -u xbps<\/code><\/pre>\n\n\n\n<p>Once xbps is current, run a full system upgrade:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo xbps-install -Syu<\/code><\/pre>\n\n\n\n<p>The <code>-S<\/code> flag syncs the remote repository index, <code>-y<\/code> confirms automatically, and <code>-u<\/code> upgrades all installed packages. If the kernel was updated, reboot before continuing:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo reboot<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Enable the Nonfree Repository<\/h2>\n\n\n\n<p>Void&#8217;s default repositories only include free software. For proprietary drivers (NVIDIA), firmware blobs, and certain codecs, you need the nonfree repo. Install it as a package:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo xbps-install void-repo-nonfree<\/code><\/pre>\n\n\n\n<p>Sync the package index so xbps picks up the new repository:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo xbps-install -S<\/code><\/pre>\n\n\n\n<p>Verify both repositories are active:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>xbps-query -L<\/code><\/pre>\n\n\n\n<p>You should see two entries listed:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code> 8404 https:\/\/repo-default.voidlinux.org\/current (RSA signed)\n    0 https:\/\/repo-default.voidlinux.org\/current\/nonfree (RSA signed)<\/code><\/pre>\n\n\n\n<p>The nonfree repo now appears alongside the main repository. Package counts will populate once you install something from it.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Set Up System Logging<\/h2>\n\n\n\n<p>Void&#8217;s base install has no logging daemon. That means kernel messages, authentication events, and service failures vanish into the void (no pun intended). The recommended solution is socklog, which integrates with runit natively.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo xbps-install socklog-void<\/code><\/pre>\n\n\n\n<p>Enable both the userspace and kernel log services:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ln -s \/etc\/sv\/socklog-unix \/var\/service\/\nsudo ln -s \/etc\/sv\/nanoklogd \/var\/service\/<\/code><\/pre>\n\n\n\n<p>Runit picks up the new symlinks within a few seconds and starts the services automatically. Logs are stored in <code>\/var\/log\/socklog\/<\/code> with subdirectories for each facility. To read recent system messages:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo svlogtail<\/code><\/pre>\n\n\n\n<p>For a specific log category like authentication events:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cat \/var\/log\/socklog\/secure\/current<\/code><\/pre>\n\n\n\n<p>Add your regular user to the <code>socklog<\/code> group so you can read logs without sudo:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo usermod -aG socklog your_username<\/code><\/pre>\n\n\n\n<p>Log out and back in for the group change to take effect.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Install Essential Tools<\/h2>\n\n\n\n<p>The base install lacks most utilities you&#8217;d expect on a working system. Install a practical set of tools in one pass:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo xbps-install htop neovim curl wget git bash-completion unzip tree<\/code><\/pre>\n\n\n\n<p>Confirm the installed versions:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>htop --version\nnvim --version | head -1\ngit --version<\/code><\/pre>\n\n\n\n<p>The output confirms the package versions pulled from the repo:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>htop 3.4.1\nNVIM v0.11.7\ngit version 2.53.0<\/code><\/pre>\n\n\n\n<p>Neovim replaces vi as your default terminal editor. If you prefer vim, install <code>vim<\/code> instead. Once you have the basics covered, you can set up more specialized software. For web server workloads, see how to <a href=\"https:\/\/computingforgeeks.com\/install-nginx-void-linux\/\" target=\"_blank\" rel=\"noreferrer noopener\">install Nginx on Void Linux<\/a> or deploy a full <a href=\"https:\/\/computingforgeeks.com\/install-lamp-stack-void-linux\/\" target=\"_blank\" rel=\"noreferrer noopener\">LAMP stack on Void Linux<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Configure the Firewall with nftables<\/h2>\n\n\n\n<p>Void has no firewall rules out of the box. Every port on the machine is wide open. nftables is the modern replacement for iptables and works well on Void with runit.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo xbps-install nftables<\/code><\/pre>\n\n\n\n<p>Create a basic firewall configuration that allows SSH, established connections, and ICMP (ping) while dropping everything else:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo vi \/etc\/nftables.conf<\/code><\/pre>\n\n\n\n<p>Add the following ruleset:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#!\/usr\/sbin\/nft -f\n\nflush ruleset\n\ntable inet filter {\n    chain input {\n        type filter hook input priority 0; policy drop;\n\n        # Allow loopback\n        iif lo accept\n\n        # Allow established and related connections\n        ct state established,related accept\n\n        # Allow ICMP (ping)\n        ip protocol icmp accept\n        ip6 nexthdr icmpv6 accept\n\n        # Allow SSH\n        tcp dport 22 accept\n    }\n\n    chain forward {\n        type filter hook forward priority 0; policy drop;\n    }\n\n    chain output {\n        type filter hook output priority 0; policy accept;\n    }\n}<\/code><\/pre>\n\n\n\n<p>Enable and start the nftables service:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ln -s \/etc\/sv\/nftables \/var\/service\/<\/code><\/pre>\n\n\n\n<p>Verify the rules are loaded:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo nft list ruleset<\/code><\/pre>\n\n\n\n<p>The output should mirror the configuration you wrote:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>table inet filter {\n\tchain input {\n\t\ttype filter hook input priority filter; policy drop;\n\t\tiif \"lo\" accept\n\t\tct state established,related accept\n\t\tip protocol icmp accept\n\t\tip6 nexthdr 58 accept\n\t\ttcp dport 22 accept\n\t}\n\n\tchain forward {\n\t\ttype filter hook forward priority filter; policy drop;\n\t}\n\n\tchain output {\n\t\ttype filter hook output priority filter; policy accept;\n\t}\n}<\/code><\/pre>\n\n\n\n<p>To open additional ports later (for example, HTTP and HTTPS), add rules before the closing brace of the input chain and reload with <code>sudo sv restart nftables<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Create a Regular User<\/h2>\n\n\n\n<p>Running everything as root is a bad habit that catches up with you eventually. Create a regular user account with a home directory:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo useradd -m -s \/bin\/bash -G wheel sysadmin\nsudo passwd sysadmin<\/code><\/pre>\n\n\n\n<p>The <code>-G wheel<\/code> flag adds the user to the wheel group, which is the standard group for sudo access on most Linux distributions. Now install and configure sudo:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo xbps-install sudo<\/code><\/pre>\n\n\n\n<p>Edit the sudoers file to allow the wheel group:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo visudo<\/code><\/pre>\n\n\n\n<p>Uncomment this line:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>%wheel ALL=(ALL) ALL<\/code><\/pre>\n\n\n\n<p>The user <code>sysadmin<\/code> can now run privileged commands with <code>sudo<\/code>. If you prefer a lighter alternative, Void also packages <code>opendoas<\/code>, which is simpler to configure and popular in the BSD world. Install it with <code>sudo xbps-install opendoas<\/code> and create <code>\/etc\/doas.conf<\/code> containing <code>permit persist :wheel<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Change the Default Shell<\/h2>\n\n\n\n<p>Bash works fine, but if you spend hours in a terminal every day, a shell with better autocompletion and syntax highlighting makes a difference. Fish is a solid choice that works well out of the box with no configuration needed.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo xbps-install fish-shell<\/code><\/pre>\n\n\n\n<p>Check the installed version:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>fish --version<\/code><\/pre>\n\n\n\n<p>This confirms fish 4.6.0 is available:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>fish, version 4.6.0<\/code><\/pre>\n\n\n\n<p>Change your default shell:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>chsh -s \/usr\/bin\/fish<\/code><\/pre>\n\n\n\n<p>Log out and back in for the change to take effect. If you prefer zsh instead, install it with <code>sudo xbps-install zsh<\/code> and run <code>chsh -s \/usr\/bin\/zsh<\/code>. Both are excellent choices, though fish requires less initial configuration.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Enable Network Time Synchronization<\/h2>\n\n\n\n<p>An accurate system clock matters more than most people realize. TLS certificate validation, log correlation, cron job timing, and build systems all depend on it. Void doesn&#8217;t enable NTP by default. Chrony is lightweight, handles intermittent connectivity well, and is the recommended NTP client for most use cases.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo xbps-install chrony<\/code><\/pre>\n\n\n\n<p>The default configuration in <code>\/etc\/chrony.conf<\/code> uses public NTP pools and works without modification for most setups. Enable the service:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ln -s \/etc\/sv\/chronyd \/var\/service\/<\/code><\/pre>\n\n\n\n<p>After a few seconds, check the synchronization status:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>chronyc tracking<\/code><\/pre>\n\n\n\n<p>The output shows your system clock&#8217;s offset from the NTP source:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Reference ID    : A29FC87B (time.cloudflare.com)\nStratum         : 3\nRef time (UTC)  : Sat Mar 29 10:15:32 2026\nSystem time     : 0.000023418 seconds fast of NTP time\nLast offset     : +0.000012354 seconds\nRMS offset      : 0.000045678 seconds\nFrequency       : 2.341 ppm slow\nResidual freq   : +0.001 ppm\nSkew            : 0.032 ppm\nRoot delay      : 0.024512 seconds\nRoot dispersion : 0.001234 seconds\nUpdate interval : 64.0 seconds\nLeap status     : Normal<\/code><\/pre>\n\n\n\n<p>A &#8220;System time&#8221; offset under 1 second means everything is working correctly.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Understanding Runit Service Management<\/h2>\n\n\n\n<p>If you&#8217;re coming from systemd, runit will feel alien at first. The core concept is simple: service definitions live in <code>\/etc\/sv\/<\/code>, and a service becomes active when you symlink it into <code>\/var\/service\/<\/code>. The runit supervisor watches <code>\/var\/service\/<\/code> and starts anything it finds there. Removing the symlink disables the service.<\/p>\n\n\n\n<p>Here&#8217;s a reference table for everyday service management:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Task<\/th><th>Runit (Void)<\/th><th>systemd equivalent<\/th><\/tr><\/thead><tbody><tr><td>Enable a service<\/td><td><code>ln -s \/etc\/sv\/SERVICE \/var\/service\/<\/code><\/td><td><code>systemctl enable SERVICE<\/code><\/td><\/tr><tr><td>Disable a service<\/td><td><code>rm \/var\/service\/SERVICE<\/code><\/td><td><code>systemctl disable SERVICE<\/code><\/td><\/tr><tr><td>Start a service<\/td><td><code>sv start SERVICE<\/code><\/td><td><code>systemctl start SERVICE<\/code><\/td><\/tr><tr><td>Stop a service<\/td><td><code>sv stop SERVICE<\/code><\/td><td><code>systemctl stop SERVICE<\/code><\/td><\/tr><tr><td>Restart a service<\/td><td><code>sv restart SERVICE<\/code><\/td><td><code>systemctl restart SERVICE<\/code><\/td><\/tr><tr><td>Check status<\/td><td><code>sv status SERVICE<\/code><\/td><td><code>systemctl status SERVICE<\/code><\/td><\/tr><tr><td>View logs<\/td><td><code>cat \/var\/log\/socklog\/SERVICE\/current<\/code><\/td><td><code>journalctl -u SERVICE<\/code><\/td><\/tr><tr><td>List enabled services<\/td><td><code>ls \/var\/service\/<\/code><\/td><td><code>systemctl list-unit-files --state=enabled<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>One thing that catches most people off guard: runit restarts services automatically if they crash. There&#8217;s no &#8220;enable and start&#8221; two-step. The moment you create the symlink in <code>\/var\/service\/<\/code>, runit starts the service and will keep restarting it if it exits. To temporarily stop a service without disabling it, use <code>sv down SERVICE<\/code>. It stays stopped until you run <code>sv up SERVICE<\/code> or reboot.<\/p>\n\n\n\n<p>To see all available services (installed but not necessarily enabled):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ls \/etc\/sv\/<\/code><\/pre>\n\n\n\n<p>Compare that to what&#8217;s actually running:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ls \/var\/service\/<\/code><\/pre>\n\n\n\n<p>The difference between those two listings tells you which services are installed but disabled.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Package Management with XBPS<\/h2>\n\n\n\n<p>XBPS is fast and straightforward once you learn the commands. The naming conventions are different from apt or dnf, but the operations map directly. Here&#8217;s a quick reference:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Task<\/th><th>XBPS command<\/th><th>apt equivalent<\/th><th>dnf equivalent<\/th><\/tr><\/thead><tbody><tr><td>Install a package<\/td><td><code>xbps-install pkg<\/code><\/td><td><code>apt install pkg<\/code><\/td><td><code>dnf install pkg<\/code><\/td><\/tr><tr><td>Remove a package<\/td><td><code>xbps-remove pkg<\/code><\/td><td><code>apt remove pkg<\/code><\/td><td><code>dnf remove pkg<\/code><\/td><\/tr><tr><td>Remove with orphans<\/td><td><code>xbps-remove -Ro pkg<\/code><\/td><td><code>apt autoremove pkg<\/code><\/td><td><code>dnf autoremove pkg<\/code><\/td><\/tr><tr><td>Search for package<\/td><td><code>xbps-query -Rs keyword<\/code><\/td><td><code>apt search keyword<\/code><\/td><td><code>dnf search keyword<\/code><\/td><\/tr><tr><td>Show package info<\/td><td><code>xbps-query -R pkg<\/code><\/td><td><code>apt show pkg<\/code><\/td><td><code>dnf info pkg<\/code><\/td><\/tr><tr><td>List installed packages<\/td><td><code>xbps-query -l<\/code><\/td><td><code>dpkg -l<\/code><\/td><td><code>rpm -qa<\/code><\/td><\/tr><tr><td>List files in package<\/td><td><code>xbps-query -f pkg<\/code><\/td><td><code>dpkg -L pkg<\/code><\/td><td><code>rpm -ql pkg<\/code><\/td><\/tr><tr><td>Sync repos<\/td><td><code>xbps-install -S<\/code><\/td><td><code>apt update<\/code><\/td><td><code>dnf makecache<\/code><\/td><\/tr><tr><td>Full system upgrade<\/td><td><code>xbps-install -Syu<\/code><\/td><td><code>apt upgrade<\/code><\/td><td><code>dnf upgrade<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>One useful trick: <code>xbps-query -Rs<\/code> searches remote repos, while <code>xbps-query -s<\/code> (without the capital R) searches only locally installed packages. The distinction matters when you&#8217;re trying to figure out whether something is already installed or just available.<\/p>\n\n\n\n<p>To clean up cached packages and reclaim disk space:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo xbps-remove -Oo<\/code><\/pre>\n\n\n\n<p>The <code>-O<\/code> flag removes cached package files, and <code>-o<\/code> removes orphaned dependencies. Run this periodically to keep the system lean.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Production Hardening<\/h2>\n\n\n\n<p>If this system will face the internet, a few additional measures bring it closer to production-ready:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>SSH key authentication<\/strong> &#8211; Copy your public key with <code>ssh-copy-id<\/code>, then disable password authentication in <code>\/etc\/ssh\/sshd_config<\/code> by setting <code>PasswordAuthentication no<\/code><\/li>\n\n\n\n<li><strong>Disable root login over SSH<\/strong> &#8211; Set <code>PermitRootLogin no<\/code> in sshd_config. Use your regular user with sudo for all administrative tasks<\/li>\n\n\n\n<li><strong>Automatic security updates<\/strong> &#8211; Add a cron job to run <code>xbps-install -Syu<\/code> nightly. Void packages move fast, and unpatched services are the most common attack vector<\/li>\n\n\n\n<li><strong>Restrict the nftables ruleset<\/strong> &#8211; Only open the ports your services actually need. The baseline config above allows SSH only, which is correct for initial setup. Add ports as you deploy services<\/li>\n\n\n\n<li><strong>Monitoring<\/strong> &#8211; Install <code>htop<\/code> for quick system checks and consider setting up a lightweight monitoring agent. For container workloads, you can also <a href=\"https:\/\/computingforgeeks.com\/install-docker-void-linux\/\" target=\"_blank\" rel=\"noreferrer noopener\">install Docker on Void Linux<\/a> and run your monitoring stack in containers<\/li>\n<\/ul>\n\n\n","protected":false},"excerpt":{"rendered":"<p>A fresh Void Linux install is minimal by design. You get a bootable system, a shell, and not much else. That&#8217;s the point. But between a bare install and a usable workstation or server, there&#8217;s a gap that needs filling: logging, firewall rules, a proper editor, time sync, and a user account that isn&#8217;t root. &#8230; <a title=\"Void Linux Post-Installation Setup Guide\" class=\"read-more\" href=\"https:\/\/computingforgeeks.com\/void-linux-post-install-setup\/\" aria-label=\"Read more about Void Linux Post-Installation Setup Guide\">Read more<\/a><\/p>\n","protected":false},"author":32,"featured_media":165022,"comment_status":"open","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[299,50],"tags":[],"class_list":["post-165027","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-how-to","category-linux-tutorials"],"_links":{"self":[{"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/posts\/165027","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/users\/32"}],"replies":[{"embeddable":true,"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/comments?post=165027"}],"version-history":[{"count":1,"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/posts\/165027\/revisions"}],"predecessor-version":[{"id":165077,"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/posts\/165027\/revisions\/165077"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/media\/165022"}],"wp:attachment":[{"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/media?parent=165027"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/categories?post=165027"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/tags?post=165027"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}