Alpine Linux on a VPS: a minimal system and its pitfalls
Alpine Linux is a distribution that takes up about a hundred megabytes of disk after installation and uses a few tens of megabytes of memory when idle. It achieves this through three choices: the musl library instead of glibc, the BusyBox utility set instead of full GNU programs, and the OpenRC init system instead of systemd. On a server this means fast boot, few unnecessary services and a small attack surface, but also a number of differences worth knowing in advance: many guides on the internet are written for Debian or Ubuntu and don't work on Alpine word for word.
What Alpine is good for
- The smallest plans with 256–512 MB of memory: where Ubuntu already feels cramped, Alpine leaves almost all the memory to your application.
- A container host. Docker and containerd install from the official repository, and the system barely gets in the containers' way. Hardware requirements are described on the VPS for Docker page.
- A reverse proxy, DNS server or private WireGuard network node: services that need networking and a couple of config files rather than a large stack of libraries.
- A throwaway server for tests and CI: the image deploys in seconds and is easy to rebuild from scratch.
Alpine is a poorer fit for sites under a control panel, proprietary software distributed only as glibc packages, and projects where the administrator isn't ready to deal with differences from the usual distributions. In those cases it's safer to choose Debian: it is also lean, but compatible with everything.
How Alpine differs from familiar Linux
- Packages are installed with apk:
apk update,apk add package,apk upgrade. The community repository may be disabled by default; uncomment it in/etc/apk/repositories. - Services are managed with OpenRC:
rc-service nginx start, andrc-update add nginxto start at boot. systemd unit files don't work here, so you write short init scripts for your own programs. - musl instead of glibc. Prebuilt binaries compiled for glibc either won't start or crash. The gcompat compatibility layer doesn't always help. For Python, some packages have no prebuilt musl builds and are compiled during installation, which is slow and requires a compiler on the server.
- No bash by default: the shell is ash from BusyBox. Scripts with bash syntax are either rewritten or bash is installed as a separate package.
- Logs are written by BusyBox syslog to
/var/log/messages; there is no journalctl.
Installation and updates
Not every host offers a ready Alpine template, and where one exists it is sometimes built from an old version. It's more reliable to install the system from the official virt image, which is made precisely for virtual machines. For this you need a KVM VPS with custom image boot and a VNC console: boot from the ISO, log in as root with no password and run setup-alpine. The script asks for the keyboard layout, network, time zone, SSH server and disk; for a server, choose the sys installation mode, which is a normal installation to disk. A list of suitable plans is on the VPS with custom ISO page.
If the host doesn't assign the address via DHCP, you'll have to configure the network manually in /etc/network/interfaces; this applies especially to IPv6. Check the network in the console before rebooting so you don't lose access.
Right after installation, set a root password, create a regular user and add an SSH key for them. Instead of sudo, Alpine often uses doas, which is smaller and simpler to configure. There is no firewall by default: install nftables, or iptables with awall, and open only SSH and the services you need. Also check the time: without chrony or ntpd a virtual machine's clock gradually drifts, and TLS certificate validation and the order of log entries depend on accurate time.
Stable Alpine releases come out twice a year, and the main repository of each is supported for about two years. Updating within a release is apk upgrade. To move to a new release, change the version number in /etc/apk/repositories and run apk upgrade --available, then reboot. Don't put the edge branch on a server: it is the development version. Alpine has no automatic updates, so set up a cron job or subscribe to the release mailing list.
What to consider when choosing a plan
Alpine needs so little memory that what matters on a plan is not memory but disk and network. Even with 512 MB there is room for nginx, a small database and a couple of containers, but don't skimp on disk if you plan to use Docker: images and layers quickly take up gigabytes. Alpine also works on container virtualisation, but there you don't choose the kernel, and modules such as WireGuard depend on the host's settings. If the server will run anything heavier than a couple of services, go straight for at least 1 GB of memory and a swap file.