Installing Vapor (and Swift) on the Raspberry Pi

Jacob Heider
4 min readFeb 17, 2020

Raspberry Pi is every tinkerer’s favorite toy [citation needed]. I’ve been using them in a variety of personal and professional settings for over five years at this point. They can do almost anything any other Linux server can do, just slower. Since I’ve recently started working in Vapor, I wanted to see if I could deploy the entire toolchain on one. Swift and ARM64 have plenty of history together, and I have a Raspberry Pi 3B+ around, so I did. If you want to do Vapor work directly on a Pi, this is for you.

I started by trying to do all of this under Raspbian, since that should be your default for Raspberry Pi projects. Sadly, there was some kind of deep incompatibility in libunwind when trying to build the Vapor toolbox, and after a number of attempts that didn’t include re-building system libraries, I decided to switch to Ubuntu, since that’s what Swift-arm was directly available for anyway. I went with 18.04 LTS, but feel free to experiment.

I’m not going to walk you through getting your Pi set up and booted to Ubuntu; the Internet is teeming with good tutorials on that. I’m going to jump right into assuming you have system working the way you want it, and are either accessing it directly, or over SSH. SSH note: some of these steps take a while, so you might want to use tmux (a little remote-system best practice for you).

First off, if you don’t want to hear a bunch of useless complaining, make sure you’ve set your basic git user identity settings:

git config --global ""
git config --global "Your Name"

We won’t be making any git commits, yet, but it does like to remind you if you forget.

Next, we need to add Swift 5 to our system. Fortunately, the fine people at Swift-Arm have not only builds for us, but apt repositories and an install script. Following along at their direction:

curl -s | sudo bash
sudo apt install swift5

With Swift installed, you should be able to check the version:

jacob@pi3:~$ swift --version
Swift version 5.1.3 (swift-5.1.3-RELEASE)
Target: aarch64-unknown-linux-gnu

Excellent. We’re some proportion of the way there. With Swift installed, we can build the Vapor toolbox (vapor command). I wasn't able to find pre-built arm64 binaries, but this wasn't a major hurdle. The biggest obstacle I faced was that the most recent commit to their repository doesn't build for me (some complex bug in a new exec flow). Fortunately, the prior tagged release (18.0.0-beta.26) builds just fine.

git clone --branch 18.0.0-beta.26
cd toolbox
swift build -c release

Grab a cup of coffee. And maybe take a walk around the block. The Raspberry Pi is not a powerful computer. Granted, the Pi 4s are out, with their wildly-upgraded specs, but I bet this still isn’t fast. On my Pi 3B+, building the Vapor toolbox took approximately five and a half minutes with no other real load running. But it builds! We’re nearly done!

sudo cp .build/release/vapor /usr/local/bin/vapor

And, with that, we have Vapor working on our Raspberry Pi. It’s exciting, right? Well, it’s not really, because we haven’t done anything with it. But that’s easily fixed. Let’s make a minimal Vapor project and get it running.

vapor new testSite

This will bootstrap our new project. For simplicity’s sake, say “no” to Fluent, Vapor’s ORM, and just build the basic project.

cd testSite
echo -e "import XCTest\n@testable import AppTests\n\nXCTMain([\n testCase(AppTests.allTests),\n])" | tee Tests/LinuxMain.swift

Vapor creates a perfectly fine scaffold for macOS, but Swift on Linux complains about the missing Tests/LinuxMain.swift when building. Fortunately, it's 7 lines of Swift, and completely predictable on a new project.

sudo apt install libssl-dev

One of our dependencies wants the SSL headers. My guess is that it’s swift-nio-ssl, but I’m never going to lose sleep over installing 6937kb of headers.

vapor build

This is the longest part. Fortunately, Swift is pretty good at incremental builds, but the first time you should be ready for a wait. Maybe a short nap, or watch a quick episode of something on TV, since this one takes almost 17 whole minutes to complete. Still, it should grab all the dependencies, load, and build them without issue.

vapor run serve

(Note that if you’re running on a remote RPi over SSH, you might prefer: vapor run serve -H to have it listen on all interfaces, so you can access it remotely.)

The moment of truth! With no mistakes made, Vapor should let us know it’s running successfully:

[ NOTICE ] Server starting on

You can either head there in a browser (running a desktop on your Pi), or switch to a new terminal and test it with curl:

curl localhost:8080

Which should return It works!.

And there you have it. A basic, but complete, webserver built with Vapor entirely on a Raspberry Pi. Happy Swifting!