Back to articles
Technology Insight

Building an Automated Mobile CI/CD Pipeline with Woodpecker CI on ARM VPS

June 4, 2026

Introduction to Modern Mobile CI/CD

In the fast-paced world of mobile application development, delivering updates quickly and reliably is a core competitive advantage. Continuous Integration and Continuous Deployment (CI/CD) pipelines have transitioned from a luxury to an absolute necessity. However, traditional CI/CD platforms can be prohibitively expensive or resource-intensive, especially for growing startups and independent development teams.

Enter the combination of Woodpecker CI and ARM-based Virtual Private Servers (VPS). Woodpecker CI, a community-driven fork of Drone CI, offers a lightweight, container-first automation engine. When paired with modern ARM64 architecture—which powers the vast majority of mobile devices today and offers exceptional performance-per-dollar ratios in the cloud—you get a highly optimized environment for building, testing, and deploying mobile applications. This guide will walk you through setting up a self-hosted mobile CI/CD pipeline from scratch.

Why Woodpecker CI and ARM VPS?

Before diving into the technical configuration, it is essential to understand why this specific stack is incredibly potent for mobile DevOps:

  • Cost Efficiency: ARM-based cloud instances (such as those from Oracle Cloud, AWS Graviton, or Hetzner) offer up to 40% better performance per dollar compared to their x86 counterparts.
  • Architecture Alignment: Since Android and iOS devices run natively on ARM, compiling and running tests on an ARM VPS reduces emulation overhead and eliminates architecture-mismatch bugs.
  • Lightweight Footprint: Unlike resource-heavy solutions like Jenkins, Woodpecker CI utilizes an extremely small memory footprint, leaving maximum system resources available for your actual build processes.
  • Container-Native Workflows: Every step in a Woodpecker pipeline runs inside an isolated Docker container, ensuring environment consistency and eliminating "it works on my machine" syndromes.

Prerequisites and Environment Setup

To follow this guide, you will need the following infrastructure and access levels:

  1. An ARM64 VPS running a modern Linux distribution (e.g., Ubuntu 22.04 LTS or newer).
  2. A registered domain name or subdomain pointed to your VPS IP address for secure SSL communication.
  3. Administrative (root/sudo) access to the server.
  4. A git repository hosted on GitHub, GitLab, or Gitea.

Step 1: Installing Docker and Docker Compose

Since Woodpecker CI relies entirely on containers, we must first install Docker on our ARM instance. Run the following commands to update your package manager and install the Docker engine:

sudo apt update && sudo apt upgrade -y
sudo apt install -y docker.io docker-compose-plugin
sudo systemctl enable --now docker

Verify the installation by checking the system architecture and Docker version using docker info. You should see aarch64 or arm64 listed under the architecture fields.

Deploying Woodpecker CI via Docker Compose

Woodpecker CI operates on a Server-Agent architecture. The server coordinates workflows and interacts with your git provider, while one or more agents execute the actual pipeline steps. We will deploy both on our single ARM VPS using Docker Compose.

Configuring the OAuth Application

Navigate to your Git provider (e.g., GitHub settings) and create a new OAuth Application. Set the Authorization Callback URL to: [https://your-ci-domain.com/login](https://your-ci-domain.com/login). Note down the generated Client ID and Client Secret.

Creating the docker-compose.yml File

Create a dedicated directory and write the configuration file:

mkdir woodpecker && cd woodpecker
nano docker-compose.yml

Paste the following production-ready configuration, making sure to replace the placeholder variables with your actual credentials:

Note: We use a shared secret token to secure the communication channel between the Woodpecker server and its executing agents. Generate a secure random string using openssl rand -hex 32.
version: '3.8'

services:
  woodpecker-server:
    image: woodpeckerci/woodpecker-server:v2.4.0
    ports:
      - "8000:8000"
    volumes:
      - woodpecker-server-data:/var/lib/woodpecker
    environment:
      - WOODPECKER_OPEN=true
      - WOODPECKER_HOST=[https://your-ci-domain.com](https://your-ci-domain.com)
      - WOODPECKER_GITHUB=true
      - WOODPECKER_GITHUB_CLIENT=your_client_id
      - WOODPECKER_GITHUB_SECRET=your_client_secret
      - WOODPECKER_AGENT_SECRET=your_generated_agent_secret
    restart: always

  woodpecker-agent:
    image: woodpeckerci/woodpecker-agent:v2.4.0
    command: agent
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - WOODPECKER_SERVER=woodpecker-server:8000
      - WOODPECKER_AGENT_SECRET=your_generated_agent_secret
      - WOODPECKER_MAX_WORKERS=2
    restart: always

volumes:
  woodpecker-server-data:

Launch the services in detached mode by running sudo docker compose up -d. To expose the web interface securely over HTTPS, set up a reverse proxy like Nginx or Caddy with Let's Encrypt certificates targeting port 8000.

Crafting the Mobile Pipeline for Android

With the platform running, we can now define our mobile CI/CD pipeline. Woodpecker uses a configuration file named .woodpecker.yml placed at the root of your repository. Because our VPS is running on ARM64, we must use a Docker image containing the Android SDK compiled for ARM64.

The .woodpecker.yml Pipeline Configuration

Create a .woodpecker.yml file in your mobile project repository with the following structural layout:

pipeline:
  environment:
    image: runmymind/docker-android-sdk:latest
    commands:
      - echo "Checking build environment..."
      - java -version
      - adb version

  lint:
    image: runmymind/docker-android-sdk:latest
    commands:
      - ./gradlew lintDebug

  unit-test:
    image: runmymind/docker-android-sdk:latest
    commands:
      - ./gradlew testDebugUnitTest

  build-apk:
    image: runmymind/docker-android-sdk:latest
    commands:
      - ./gradlew assembleRelease

  publish:
    image: plugins/firebase-distribution
    settings:
      app: internal-app-id
      token: 
        from_secret: firebase_token
      groups: qa-testers
      file: app/build/outputs/apk/release/app-release.apk
    when:
      branch: main

Let's dissect the critical parts of this pipeline:

  • Isolated Steps: Each top-level key under pipeline represents a sequential stage. If the lint or unit-test stage fails, the pipeline halts immediately, preventing broken builds from progressing.
  • Secrets Handling: Sensitive items like API keys or deployment tokens are never hardcoded. Instead, they are safely referenced using from_secret and managed via the Woodpecker web UI dashboard.
  • Conditional Execution: The when block ensures that automated deployment to testers only triggers when code is merged successfully into the main production branch.

Optimizing Pipeline Performance on ARM

Mobile builds are notoriously resource-intensive. To prevent your ARM VPS from choking during high-concurrency periods, implement these optimization strategies:

1. Cache Dependencies

Downloading Gradle dependencies or Node modules on every single run destroys pipeline efficiency. Integrate the Woodpecker volume cache plugin to persist download caches across sequential builds:

  restore-cache:
    image: meltwater/drone-cache
    settings:
      backend: "filesystem"
      restore: true
      cache_key: '{{ .Commit.Branch }}'
      mount:
        - .gradle

  # ... build steps go here ...

  rebuild-cache:
    image: meltwater/drone-cache
    settings:
      backend: "filesystem"
      rebuild: true
      cache_key: '{{ .Commit.Branch }}'
      mount:
        - .gradle

2. Tuning Gradle Resources

By default, Gradle tries to allocate resources aggressively. Force it to behave within your VPS limitations by adding these flags to your project's gradle.properties file:

org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m
org.gradle.daemon=false
org.gradle.parallel=true

Conclusion and Next Steps

Building an automated CI/CD pipeline for mobile applications using Woodpecker CI on an ARM VPS provides an elite balance of performance, strict environmental control, and minimal infrastructure costs. By self-hosting this lightweight system, modern engineering teams gain full control over data privacy and build speeds without suffering from the compounding monthly costs associated with proprietary cloud builders.

As next steps, consider expanding your setup by integrating automated code signing keys safely into Woodpecker secrets, utilizing Matrix builds to test across multiple build flavors concurrently, or attaching additional external ARM runners to distribute massive workloads seamlessly.