Deploying Source Control


A key component of a proper devops setup is Infrastructure as Code. This is the concept that you deploy your infrastructure using a series of config files, and track changes using a version control system.

A key part of doing so is having a proper version control system! Github is by far the most popular hosted platform, but for our setup we will deploy our own selfhosted gitea setup.


In this section, we will:

  • Deploy Gitea as a version control system in rancher


Let’s create a new subdomain for this service. I will call it git...

Crafting the Environment Variables

The first step for any moderately complex setup is getting our environment variables sorted. While we can deploy environment variables directly in the deployment, it’s better practice to store variables as a secret. We will do so now:

  • In Storage→Secrets, Create a new secret

  • Create an opaque secret called gitea with the following changing:
    • The database password for another password
    • The Root URL for another root URL
USER_UID: 1000
USER_GID: 1000
GITEA__database__DB_TYPE: postgres
GITEA__database__NAME: gitea
GITEA__database__USER: gitea
GITEA__database__PASSWD: CHANGEME-Claw3-Unfair-Drab

You can paste YAML formatted environment data directly into rancher. You will get an error about the UI not supporting the data, but if you save and return the UI will sort itself out.

You may notice that we are connecting to the database host on This is because we will be deploying gitea as a pod, and pods can communicate over localhost (or

Deploying the Database

  • Under Workload→Deployments, create a new deployment

In a production setup, you would deploy stateful containers (like postgres) as a StatefulSet. StatefulSets require more configuration and can break easier, but allow scaling in a way that maintains volume→container pairings. For simplicity, we are sticking to normal Deployments (which is fine as we don’t plan to scale beyond a single replica).

  • Name the deployment gitea and set the container name to postgres. Set the image to postgres:13

we don’t use postgres:latest because changing major versions of postgres (typically) require a manual migration step

  • Under Environment Variables set the POSTGRES_DB, POSTGRES_USER, and POSTGRES_PASSWORD to use the gitea secret and associated keys.

  • Under Health Check→Startup Check set the container to check for TCP port 5432.

It is good practice to set up a startup check on any container you plan to permanently deploy. This allows for an easy check to see when containers are failing (like after an update), and allow for automatic restarts. You can also optionally set readiness/liveness checks for ongoing health checks.

  • Under Scaling and Upgrade Policy, set the pod to recreate instead of rolling update

By recreating the pod on update, we experience a small downtime on upgrade. However, this prevents two deployments sharing the same volume, potentially corrupting it.

  • Under Storage→Create Persistent Volume Claim, create a claim with the gitea-db name, storage class of longhorn, capacity of 5gb, access mode of single-node read/write, volume name of gitea-db-vol, and mount point of /var/lib/postgresql/data. Create a sub path called db Press create.

Postgres doesn’t like being in the root of a volume, which is why we created a subfolder inside the volume for Postgres.

  • If all goes well, you should get an active deployment running your postgres db!

Deploying Gitea

We’re only halfway there yet. We got postgres going, but not gitea. Let’s go back and edit the deployment.

  • Under the container dropdown, choose add container

  • Set the container name to gitea. Set the image to gitea/gitea:latest. Under ports, create a cluster IP with the name http and the port 3000.

  • Set all of your environment variables to match the variables created in the gitea secret:

  • Under health check, check for port 3000

  • Under Storage, create a persistent volume claim. Name the claim gitea-data and set the storage class to longhorn. Set the capacity to 10gb and Access Mode to Single-Node Read/Write. Set the volume name to gitea-data-vol and the mount point to /data. Save the deployment.

If all goes well, the gitea deployment should update and become active. If there are problems, you can check the log of either container by navigating to the deployment (or using pods in the sidebar), and using the dropdown to view logs.

Setting the Ingress

Almost there! Under Service Discovery→Ingresses, Create a new Ingress

  • Set the ingress name to gitea. Set the host to git... Set the prefix to / and choose your gitea service from the dropdown.

  • Under certificates, use the let’s encrypt certificate you generated with your DNS challenge

If you used the http01 let’s encrypt method, you will need to go into certificates and clone your helloworld certificate, cloning it for the git subdomain

  • Under Labels & Annotations, set the HTTPS force redirect and create:

Initial Setup

If all has gone well, you can now access your source control on! All of the fields should be prepopulated except for your admin user. Create an admin user and install gitea.


Well first off, congratulations! You have now deployed a complex app with a separate database and multiple secrets, with a valid let’s encrypt certificate.

That said, there sure was a ton of pointing and clicking involved with that. This goes against our ethos of Infrastructure as Code. Let’s learn how to create reproducible kubernetes deployments with kubernetes manifests.