Ship Vapor and Hummingbird without the systemd unit.
Push a SwiftPM package and Provisore builds it on your server, runs the binary under systemd, and puts Nginx with a renewing Let's Encrypt certificate in front. No Dockerfile, no CI job, no image registry. Laravel and Node sites deploy through the same pipeline.
What a deploy does
Five steps, none of which you write.
- Push to your branch
- The GitHub App sends a webhook and Provisore clones the commit into a new release directory. There is no CI job to set up and no image to publish.
- swift build -c release, on the server
- Provisore installs the toolchain from swift.org on the server itself, Swift 6.4.0 unless the site or a .swift-version file in the repository names another. The binary is built against the glibc it runs on, and nothing is cross-compiled.
- A build cache per site
- Each site keeps its SwiftPM build directory between deploys, and a new toolchain version starts it fresh. One measured redeploy on a four-core server took 21 seconds warm against 1,058 cold. The build checks free disk before it starts and sizes its parallelism to the memory available, so a small server builds slower instead of dying with signal 9.
- systemd runs the binary
- The binary runs under a systemd unit as the site's own user, with the site's .env loaded as its environment. Provisore assigns the port and hands it over the way each framework reads it: serve --hostname --port for Vapor, HTTP_HOST and HTTP_PORT for Hummingbird. A fresh project from either template starts unchanged. The service restarts on failure and comes back after a reboot.
- Nginx in front, swapped atomically
- Nginx proxies the port and terminates TLS with a Let's Encrypt certificate that renews itself. Activation is a symlink swap behind a health check, and earlier releases stay on disk for rollback.
The unit you did not have to write
Provisore assigns the port, writes the unit, and reloads systemd on every activation. You name the executable under Settings → Source on the site, and never open this file.
[Service] Type=simple User=p-feed-nordapi-com-3f1c9ab2 Group=p-feed-nordapi-com-3f1c9ab2 WorkingDirectory=/home/provisore/sites/feed.nordapi.com/current ExecStartPre=+/usr/local/lib/provisore/site-environment feed.nordapi.com %n EnvironmentFile=-/run/provisore/site-environment/%n.env Environment=PORT=30412 Environment=HTTP_HOST=127.0.0.1 Environment=HTTP_PORT=30412 ExecStart=/usr/bin/env bash /home/provisore/sites/feed.nordapi.com/shared/start-command Restart=on-failure RestartSec=3
On Ubuntu 26.04, Swift sites need 6.4.0 or newer
New servers start on Ubuntu 26.04. swift.org builds its Ubuntu 26.04 toolchains from Swift 6.4.0 onwards, so a repository whose .swift-version pins an older Swift needs an Ubuntu 24.04 server, which takes toolchains back to 5.10.1. The release is fixed when you add the server. Everything else on this page applies to both.
Swift 6.4.0 by default, Ubuntu 26.04 or Ubuntu 24.04 LTS, Nginx with Let’s Encrypt
Everything the other runtimes get
Same isolation, same rollbacks, same logs. A Swift site is one more runtime in the same pipeline.
- Its own Unix user
- Each site runs as its own account, so one site cannot read another's .env or deploy key.
- Rollback and history
- Releases stay on disk. Roll back to an earlier one from the site's Deployments page.
- Queues, cron and logs
- Daemons for queue workers, scheduled tasks, and live logs in the console dock, the same as a Laravel site gets.
Put your Swift service in production.
Point Provisore at a repository with a Package.swift, name the executable, and push. 14 days free on every plan.