Easily deploy your Vapor 4 API to a VPS with these simple steps with GitHub Actions (CI/CD)

Vishweshwaran
7 min readFeb 18, 2023

Are you tired of relying on those overpriced API hosting platforms that just won’t cooperate? Fear not, my friend! In this article, I’ll show you how to take control of your API destiny and deploy it to a VPS like a true boss. There are six steps involved in deploying VaporAPI to a VPS using GitHub Actions.

Let’s get started.

Steps to be followed:

  1. Configuring the VPS
  2. Setting up the VPS
  3. Creating a Dockerfile
  4. Continuous Integration
  5. Setting up GitHub Actions
  6. Continuous Deployment

1. Configuring the VPS

You are free to select your own VPS provider. This technique is applicable to any VPS. Whereas I use Contabo VPS because it is less expensive than other VPS providers. Once you’ve decided on a VPS provider. In order to login securely to your VPS, we must add SSH Authentication to your server.

How to Generate SSH Keys

Open a terminal on your local machine and enter the following command to generate a pair of keys (assuming your local computer runs MacOS)

ssh-keygen -t rsa

When you’re prompted to “Enter a file in which to save the key”, you can press Enter to accept the default file location. And here’s the default path for the saved keys: ~/.ssh

While id_rsa is your private key, id_rsa.pub is your public key.

How to Upload SSH Public Keys to Your Server

You must copy and paste your public key into your VPS after generating the private and public keys.

pbcopy < ~/.ssh/id_rsa.pub
# Copies the contents of the id_ed25519.pub file to your clipboard

Tip: If pbcopy isn't working, you can locate the hidden .ssh folder, open the file in your favourite text editor, and copy it to your clipboard.

Log in to your VPS via SSH as root. With this command you can create the right directory and switch to it at the same time:

mkdir /root/.ssh && cd /root/.ssh

Now create and open the authorized_keys text file with this command:

nano authorized_keys

Paste in your whole public key and save the file by pressing [CTRL+O]. To exit the editor use [CTRL+X]

2. Setting up the VPS

Deploying a Vapor can be done in a number of different ways, including using DigitalOcean, Fly, Heroku, Supervisor, Systemd, Nginx, or Docker. In our case, I’ll be using Docker.

Use this link to install Docker on your VPS https://docsdocker.com/engine/install/ubuntu/

To see if docker is installed, run the following command:

docker --version
Docker version 20.10.12, build 20.10.12-0ubuntu2~20.04.1

3. Creating Dockerfile

To begin with I’m going to use one of my Vapor APIs. https://github.com/VishwaiOSDev/IP2GeoVapor

IP2GeoVapor: IP2Geo is a Vapor API that allows you to easily fetch geographical information of an IP address. The IP-API service uses HTTP by default, but this package uses HTTPS to ensure a secure connection.

Docker is a platform that allows developers to package their applications and dependencies into a single container, making it easier to deploy and run the application in different environments.

# 1 Use the latest version of the official Swift Docker image
FROM swift:5.7

# 2 Set the working directory in the container
WORKDIR /app

# 3 Copy the contents of the local directory to the container
COPY . .

# 4 Build the Swift Vapor API
RUN swift build

# 5
RUN mkdir /app/bin
RUN mv `swift build --show-bin-path` /app/bin

# 6
EXPOSE 3001
ENTRYPOINT ./bin/debug/Run serve --env local --hostname 0.0.0.0
  1. FROM swift:5.7: This specifies the base image to use for the Docker container, which in this case is the official Swift 5.7 image.
  2. WORKDIR /app: This sets the working directory inside the container to /app.
  3. COPY . .: This copies the contents of the current directory into the /app directory in the container.
  4. RUN swift build: This builds the Swift Vapor API in debug mode.
# 5
RUN mkdir /app/bin
RUN mv `swift build --show-bin-path` /app/bin

5. This creates a new directory /app/bin in the container, and moves the binary built by the swift build command to the /app/bin directory.

6. EXPOSE 3001: This exposes port 3001 to the host machine so that it can access the Swift Vapor API running inside the container.

7. ENTRYPOINT ./bin/debug/Run serve --env local --hostname 0.0.0.0: This specifies the command to run when the container is started. In this case, it runs the serve command of the Swift Vapor API binary, passing it the --env local --hostname 0.0.0.0 flags. The API is run in debug mode by default, using the binary located in /app/bin/debug.

That’s it! This Dockerfile builds a container that runs a Swift Vapor API in debug mode, with the option to modify it to run in release mode by building the API with the -c release flag and changing the ENTRYPOINT command to use the release binary.

4. Continuous Integration

Proceed with Continuous Integration (CI) CI Actions must be triggered when submitting a Pull Request to the main/master branch on GitHub.

This GitHub Actions workflow is designed to build and test a Swift project when a pull request is opened or updated on the main branch. The workflow consists of four steps:

  1. Install Swift: This step installs the Swift programming language on the virtual machine which GitHub Actions uses to run the workflow. It uses the “slashmo/install-swift” action to download and install the Swift version 5.6.
  2. Checkout: This step checks out the code from the pull request branch. This is necessary so that the subsequent steps can build and test the code.
  3. Cache: This step caches the build artifacts, checkouts, repositories, and workspace state files. Caching these files can speed up the build and test process, since the workflow does not need to rebuild everything from scratch every time it runs. The cache key is based on the operating system running the workflow and the contents of the “Package.swift” and “Package.resolved” files, which describe the dependencies of the Swift project.
  4. Build and Test: This step runs the “swift test” command, which builds and tests the Swift project. This command uses the cached build artifacts, checkouts, and repositories to speed up the build and test process.

5. Setting up GitHub Actions

Now we’re ready to move on to setting the secret variables in GitHub.

Head to your repo in GitHub that needs the variables and click on the Settings tab. Inside Settings, go down the sidebar to the Secrets dropdown and click on it to access the Actions page. The page should look something like this image below.

In my Actions Secrets page, there are already a few Repository Secrets present — this is what we’ll be adding to run in the GH Actions workflow. Click on the New repository secret button in the upper right corner of the screen.

To add new secrets to the repository, a new screen will appear. To access our VPS, we need HOST, USERNAME, PORT, and SSHKEY. HOST is the IPAddress, and the port is 22. For example, host will be accessed by:

HOST: ${{ secrets.HOST }}

6. Continuous Deployment

Once the pull request has been approved and merged into the main Continuous Deployment (CD) actions will run.

  1. The workflow is triggered by code pushes to the main branch, but ignores changes to markdown files.
  2. The job defined in the workflow is called “deploy”, and runs on the latest version of Ubuntu.
  3. The job has a single step, which uses the appleboy/ssh-action action to connect to a remote server using SSH and execute deployment commands.
  4. Connect to the remote server using SSH and navigate to the project directory.
  5. Reset the Git repository to its previous state to discard any local changes that may have been made on the remote server.
  6. Pull the latest changes from the repository to update the code on the remote server.
  7. Stop and remove any existing Docker container for the API (if one exists) to avoid conflicts.
  8. Build a new Docker container using the updated code.
  9. Run the new Docker container in detached mode, binding port 3001 to the host machine, to make the API accessible.
  10. Prune all unused Docker images from the system to free up disk space and keep the system clean.

By performing these steps automatically using GitHub Actions, this workflow helps ensure that the deployed version of the API is always up-to-date and free of any local changes or conflicts, and that the Docker images on the remote server do not accumulate over time.

Conclusion

Now that you’ve deployed your Vapor 4 API to a VPS like a boss, go ahead and treat yourself to a well-deserved cup of coffee or tea. And remember, never underestimate the power of a developer who knows how to wield a VPS!

--

--

Vishweshwaran

A seasoned iOS Developer, building and maintaining apps across a diverse range of industries. I have a keen eye for detail and leverage the latest technologies