Run a continuous integration server on a Quake AI VM to watch your repositories, queue pipelines, and dispatch build jobs. A CI server is the orchestrator that schedules work. It is one component above a single CI runner, which is the agent that executes one job. If you only need an agent that plugs into GitHub Actions or GitLab CI, deploy a self-hosted CI runner instead.
Self-hosted CI covers a range of software, from container-native servers that run in a few hundred megabytes of RAM to plugin-rich servers that need 4 GB of RAM or more. This guide gives you one host pattern that runs any of them, a recommended default for small teams, and the sizing and persistence adjustments the heavier servers need.
Click to zoom
The host pattern: a VM runs the CI server in Docker, build data lives on an attached volume, a security group fronts the web UI and webhook traffic, and the git provider triggers pipelines
Pick a VM tier from the workload, then create the instance:
Lightweight, container-native servers (Woodpecker, Drone, the Forgejo Actions runner) run comfortably on a small shared-vCPU tier for a single team. Give them headroom for the build jobs themselves, which are heavier than the server.
Heavyweight servers (Jenkins-class) want at least 2 vCPUs and 4 GB of RAM for the server alone, plus more for concurrent builds. Plan for disk growth from plugins and artifacts.
Create the instance from the Compute how-to, or provision it as code from the Simple VM template. Assign a floating IP so the git provider can reach the webhook endpoint.
Step 2: Attach a persistent volume for build data#
A CI server accumulates state you do not want to lose on a rebuild: server configuration, encrypted credentials, pipeline history, and caches. Keep that state on a block volume rather than the root disk, so you can detach it, snapshot it, and reattach it to a replacement VM.
Create and attach a volume from the block storage how-to, then mount it on the host. Confirm the device path before you format: run openstack volume show VOLUME_NAME -c attachments or lsblk inside the instance. On Quake AI, the first attached data volume appears as /dev/sdb.
bash
sudo mkfs.ext4 /dev/sdbsudo mkdir -p /srv/ciecho '/dev/sdb /srv/ci ext4 defaults,nofail 0 2' | sudo tee -a /etc/fstabsudo mount /srv/ci
Point your server's data directory at /srv/ci when you run it in Step 5. Confirm the mount before continuing:
A CI server needs a small, deliberate set of inbound ports. Add rules to the instance's security group:
Port
Source
Purpose
443 (HTTPS)
Your team's IP ranges, or a VPN
Web UI and API behind TLS
22 (SSH)
Your admin IP ranges
Host administration
Webhook port
Your git provider's published IP ranges
Pipeline triggers on push
Restrict each rule to the narrowest source range that works. A CI server holds deploy credentials, so an open 0.0.0.0/0 web UI is a standing risk. Terminate TLS at a reverse proxy on the host (for example Caddy or nginx) and serve the UI over HTTPS only.
Add your user to the Docker group so you can run commands without sudo:
sudo usermod -aG docker ubuntu
newgrp docker
Group membership changes take effect on your next login. The newgrp docker line above activates the group in your current shell. If you skip it or open a new shell, log out and SSH back in before you run docker commands.
Confirm the install with a command that needs the daemon socket:
docker run --rm hello-world
A daemon-less check such as docker --version passes even when the group is not active yet, so it hides this gotcha.
With the host, the volume, the ports, and Docker in place, run the server of your choice. Bind its data directory to the /srv/ci mount so its state lives on the persistent volume.
For a small team or a solo developer, a container-native server is the recommended default. These servers are built to run as containers, carry a modest memory footprint, and define pipelines as files in your repository:
Woodpecker CI is a community fork of Drone with a small server and per-pipeline runner agents. It connects to GitHub, GitLab, Gitea, and Forgejo.
Drone uses the same container-per-step model and a single configuration file per repository.
The Forgejo Actions runner (and the equivalent Gitea Actions runner) reuses GitHub Actions workflow syntax against a self-hosted forge. If you already run a self-hosted git forge, this keeps CI on the same host pattern.
Woodpecker as a representative example wires into the Compose file from Step 5: set the server image, the volume mount, and your git provider's OAuth credentials, then register a runner agent against the server. Pipeline definitions live in your repository, so the server holds only configuration and history on /srv/ci.
Plugin-rich servers in the Jenkins class (Jenkins as the representative, with TeamCity and similar belonging to the same bucket) trade a larger footprint for a deep ecosystem of plugins and integrations. The host pattern above runs them with three adjustments:
More compute. Give the server at least 2 vCPUs and 4 GB of RAM before adding build executors. Each concurrent build adds to that.
State on the volume. Put the server's home directory (for Jenkins, JENKINS_HOME) on the /srv/ci mount. It holds job configuration, plugins, credentials, and build history.
Disk planning. Plugins, build logs, and artifacts grow over time. Size the volume for that growth and prune old build data on a schedule.
You install, run, and operate these servers yourself on the VM. Quake AI provides the infrastructure underneath; the CI server is software you manage.
A CI server runs for months and holds the credentials that deploy your software. Treat it as production infrastructure:
Front it with TLS. Serve the UI over HTTPS through a reverse proxy. Do not expose the raw server port.
Limit who can reach it. Restrict the web UI and SSH to your team's IP ranges or a VPN, as in Step 3.
Protect the admin account. Set a strong password, enable single sign-on where the server supports it, and define least-privilege roles for everyone else.
The persistent volume holds the state that makes the server reproducible: configuration, credentials, plugins, and build history. Back it up so you can restore the server onto a fresh VM:
The sample code, software libraries, command line tools, proofs of concept, templates, and other related technology on this page (including any of the foregoing that is provided by Quake AI personnel) is provided to you as Quake AI Content under the Quake AI Customer Agreement, or the relevant written agreement between you and Quake AI (whichever applies). Do not use this Quake AI Content in your production accounts, or on production or other critical data. You are responsible for testing, securing, and optimizing the Quake AI Content (such as sample code) as appropriate for production grade use based on your specific quality control practices and standards. Deploying Quake AI Content may incur Quake AI charges for creating or using Quake AI chargeable resources, such as running Compute instances or storing data in Object Storage. Your use is also subject to the Acceptable Use Policy.