In this tutorial we will setup Gitea as our version control system, and we will setup Woodpecker Ci (Server and Agent) to run our builds from a simple pipeline that we define in yaml, and the best is that our builds runs on containers. We will run these on docker and make use of docker-compose.

What is Woodpecker

Taken from their documentation: “Woodpecker is a simple CI engine with great extensibility. It runs your pipelines inside containers, so if you are already using them in your daily workflow, you’ll love Woodpecker for sure.”

You can read more about them here


This stack will boot the following:

  • Gitea (Version Control)
  • Woodpecker Server (Control Plane)
  • Woodpecker Agent (Responsible for running builds)

The source code for this can be found on my Github Repository


We will need the IP Address of your workstation (LAN), in order to enable the containers to communicate with each other (woodpecker-server and gitea).

This can be retrieved by running:

ifconfig $(netstat -rn | grep -E "^default|^" | head -1 | awk '{print $NF}') | grep 'inet ' | awk '{print $2}' | grep -Eo '([0-9]*\.){3}[0-9]*'

In my case the output is:

Set that to the environment:

export IP_ADDRESS=$(ifconfig $(netstat -rn | grep -E "^default|^" | head -1 | awk '{print $NF}') | grep 'inet ' | awk '{print $2}' | grep -Eo '([0-9]*\.){3}[0-9]*')

# or

export IP_ADDRESS= # replace with your ip address


Run the gitea container:

docker-compose up -d woodpecker-gitea

Access gitea on http://git.${IP_ADDRESS}, to display the url in your terminal:

echo http://git.${IP_ADDRESS}

Most of the defaults should be populated as we defined them in our environments section of our compose, at the bottom, provide the administrator details, then select “Install Gitea”:


Then you should be redirected to the main gitea menu:


At this point in time we need to setup a OAuth application in order for our Woodpecker Server to authenticate with Gitea. Select the profile at the right top corner, then select settings:


Then select the “Applications” tab, then under “Manage OAuth2 Applications”, provide the following:

  • Application Name: Woodpecker CI
  • Redirect URI:


Then click “Create Application” and you should get the following values:

  • Client ID: c587c627-cc4e-4fb1-a196-97736051090b # values has been deleted
  • Client Secret: u92Jvf-gxj_phcRnHWjwpmJv0NXoWthNGsXybds6CuE= # values has been deleted

Then select “Save”


Time to configure the woodpecker server and agent, and all that we need to configure is the .env file so that we can make woodpecker aware of the gitea client and secret and as well as the woodpecker agent secret which is a shared secret between the woodpecker server and agent.

First let’s create a agent secret:

$ openssl rand -base64 32

Then we will populate the gitea client and secret that we retrieved from gitea, and the agent secret that we received from the openssl command in the .env file:


Once that is in place, we can start the woodpecker server and agent containers:

docker-compose up -d

Now access woodpecker server on http://ci.${IP_ADDRESS}, to return the address in your terminal:

echo http://ci.${IP_ADDRESS}

On the initial page we will see the login screen:


Once we select login, we will be redirected to gitea where it will ask us if we authorize woodpecker ci (the application that we created) to access our gitea account:


Select “Authorize Application”, then we will be logged into woodpecker server:


Head back to gitea, and from the top right hand corner, select “+” and select “New Repository”:


Provide a repository name and select “Initialize Repository”:


Then select “Create Repository”:


Head back to woodpecker server, then on the right hand side select “Add Repository”:


Then select “Reload Repositories”, and you should see your repository appear:


Then select “enable” and you should see a view with no builds:


Head back to gitea, select “new file”, name the file .woodpecker.yml and provide this basic pipeline yaml:

    image: busybox
      - echo "first run"

And what we do, we specify that our build should run a container from a busybox image, and run the command echo first run.

Commit the file to the master branch, then head back to woodpecker server, we will see that from the pipeline overview page, that our build succeeded:


When we select the build, we can see our build consisted of a clone step and our step which we called “first-job”:


Example Pipelines

The following pipeline will run a mysql service container and our build step will use a container from the mysql image, to test the connectivity to the mysql service, it will retry until it establishes a connection and then exit:

    image: mysql:5.7
      - while ! mysqladmin ping -h mysql-server -u woodpecker -pwoodpecker --silent; do sleep 1; done

    image: mysql:5.7
      MYSQL_DATABASE: woodpecker
      MYSQL_USER: woodpecker
      MYSQL_PASSWORD: woodpecker

The following pipeline will run two steps in parallel (run-one and run-two) as they share the same group name, then step run-three will run after that, and we define the pipeline to only trigger when the branches includes master and any prefixes starts with releases/. The pipeline will not trigger on branches starting with test/1.0.0 and test/1.1.*:

    image: busybox
    group: first
      - echo "first run"

    image: busybox
    group: first
      - echo "second run"

    image: ubuntu
      - echo hi
    include: [ master, release/* ]
    exclude: [ test/1.0.0, test/1.1.* ]

For more information on the pipeline syntax, view:

For more examples, see their repository:

Thank You

Thanks for reading, if you like the project, feel free to star, fork or share it, check out my website, read my newsletter or follow me at @ruanbekker on Twitter.