All templates

cubeshipd/cubeship-gitea-template

Gitea

Gitea: lightweight self-hosted Git service, over HTTPS

Gitea on Cubeship

Gitea is a lightweight self-hosted Git service: repositories, pull requests, issues, wikis, packages and a container registry, in one Go binary.

This template installs it on a Cubeship instance, with the managed Postgres it keeps users, issues and settings in, and volumes for the repositories and its configuration.

What it creates

  • gitea — Gitea, from gitea/gitea:1.27.3-rootless, answering on the domain you choose, with two volumes:
    • /var/lib/gitea — every repository, LFS objects, attachments and avatars.
    • /etc/giteaapp.ini, including the internal token and signing secrets Gitea generates on its first start.
  • gitea-db — a managed Postgres 16 database, holding users, organizations, issues, pull requests and settings.

It needs Cubeship 0.7.0 or newer.

The web installer is skipped: the database, the URL and the secret key are set by the app's variables, and INSTALL_LOCK is on.

What you are asked

InputWhat to give
Where Gitea answersA domain you control, pointed at your instance. It also becomes ROOT_URL.
The key Gitea encrypts stored secrets withNothing — the instance generates it and shows it once. Keep a copy: a new key cannot read two-factor secrets and other values encrypted under the old one.

After installing

  1. Open the domain straight away and register. The first account registered becomes the site administrator. Until you do, that is anyone who finds the domain.

  2. Close registration, unless you want anyone to sign up. On the gitea app, set GITEA__service__DISABLE_REGISTRATION to true and redeploy. From the CLI:

    cubeship app env set gitea/production/gitea GITEA__service__DISABLE_REGISTRATION=true
    cubeship app deploy gitea/production/gitea
    

    Add people afterwards under Site Administration → User Accounts.

To create the administrator instead of registering one, run Gitea's own command over SSH on the machine the app runs on — Cubeship has no console into an app:

docker exec -it $(docker ps -qf name=cubeship-gitea-production-gitea) \
  gitea admin user create --admin --username <name> --email <address> --random-password

It prints the password; change it after signing in. The same gitea admin user change-password --username <name> --password <new> resets a forgotten one.

Git over HTTPS only

Clone, pull and push over https://<your domain>/<owner>/<repo>.git. Git over SSH does not work: it needs a TCP port — 22 or 2222 — reachable from outside, and Cubeship cannot expose a port other than a domain's HTTP. SSH is turned off, so Gitea shows only HTTPS clone URLs and does not offer SSH keys.

Push with your password, or with an access token made under Settings → Applications — required once two-factor sign-in is on. Git LFS works over the same URL.

Settings in variables

Any app.ini setting can be set on the app as GITEA__<section>__<KEY>GITEA__mailer__ENABLED, GITEA__service__REQUIRE_SIGNIN_VIEW — and applied by redeploying. Gitea writes them into app.ini on every start, so a variable wins over anything edited in the file. See upstream's configuration cheat sheet.

Mail

No mail is set up, and Gitea runs without it — but then nobody gets notifications, and a forgotten password is only reset over SSH. To add it, set these on the app and redeploy:

VariableValue
GITEA__mailer__ENABLEDtrue
GITEA__mailer__PROTOCOLsmtp+starttls for port 587, smtps for 465.
GITEA__mailer__SMTP_ADDRYour provider's host.
GITEA__mailer__SMTP_PORT587 or 465.
GITEA__mailer__USERFrom your provider.
GITEA__mailer__PASSWDFrom your provider.
GITEA__mailer__FROMAn address your provider lets you send as.

Actions

Gitea Actions is on, but no runner is included, so workflows stay queued. The runner, act_runner, starts a container for every job and needs the Docker socket, which Cubeship does not give an app. Run it on another machine with Docker, registered against https://<your domain> with a token from Site Administration → Actions → Runners — see upstream's act_runner guide. To hide Actions instead, set GITEA__actions__ENABLED to false.

The volumes

The app runs as one copy on the machine its volumes are on, and a deploy stops it for a few seconds, during which nobody can push or pull. Back up both volumes and the database together: the repositories are in one, and who owns them and every issue about them is in the other.

Resources

The app is limited to 1 CPU and 1 GiB of memory, comfortable for a small team. Large repositories, many mirrors or code search indexing need more: raise limits in template.yaml.

What this creates

gitea

gitea/gitea:1.27.3-rootless

gitea-db

Postgres 16

/var/lib/gitea

Volume of gitea

/etc/gitea

Volume of gitea

template.yaml
# yaml-language-server: $schema=https://cubeship.dev/schema/template/v1.json
version: 1
# The first release that keeps a volume's data across deploys.
minCubeship: "0.7.0"
project: gitea

inputs:
  - key: domain
    type: domain
    label: Where Gitea answers
  - key: secretKey
    type: secret
    label: The key Gitea encrypts stored secrets with
    help: Keep a copy. Without it, two-factor secrets and other encrypted settings cannot be read again.
    generate: 64

databases:
  - key: db
    name: gitea-db
    engine: postgres
    version: "16"
    database: gitea

apps:
  - key: web
    name: gitea
    image: gitea/gitea
    # The rootless image: no OpenSSH server to supervise, and SSH cannot be
    # exposed here anyway.
    tag: "1.27.3-rootless"
    port: 3000
    health: /api/healthz
    domains:
      - host: ${input.domain}
    volumes:
      # Repositories, LFS objects, attachments and avatars.
      - path: /var/lib/gitea
      # app.ini, where Gitea saves the tokens it generates on first start.
      - path: /etc/gitea
    limits: { cpu: 1, memory: 1Gi }
    env:
      # Written into app.ini on every start, so these always win over it.
      GITEA__database__DB_TYPE: postgres
      GITEA__database__HOST: ${db.db.host}:${db.db.port}
      GITEA__database__NAME: ${db.db.name}
      GITEA__database__USER: ${db.db.user}
      GITEA__database__PASSWD: ${db.db.password}
      GITEA__database__SSL_MODE: disable
      GITEA__server__ROOT_URL: https://${input.domain}/
      GITEA__server__DOMAIN: ${input.domain}
      GITEA__server__DISABLE_SSH: "true"
      GITEA__server__START_SSH_SERVER: "false"
      GITEA__server__LFS_START_SERVER: "true"
      # Skips the web installer.
      GITEA__security__INSTALL_LOCK: "true"
      GITEA__security__SECRET_KEY: ${input.secretKey}