Build a Lightweight Internal Git and Script Catalog with Gitea
Run a small Gitea instance from the current rootless container image, keep the web service behind an internal HTTPS boundary, and prove the catalog by creating, cloning, and...
Expected Outcome
A working internal Gitea script catalog with persistent data/config volumes, a private repository, and a validated clone-edit-push workflow over the intended internal URL.
Assumptions
A Linux host with Docker Engine and Docker Compose v2.
An internal DNS name such as `git.example.internal` and an HTTPS reverse proxy if the catalog will be used from other machines.
Git installed on a separate workstation for clone/push validation.
Enough storage to retain Gitea repositories and configuration outside the container lifecycle.
Bill of Materials
Current Gitea rootless container image from `docker.gitea.com`.
An internal TLS certificate path trusted by the workstations that will use the catalog.
One small non-sensitive test script and README.
Build Steps
- Verify Compose v2 and create the service directory
Gitea's current Docker documentation uses Compose v2. Do not install the retired standalone docker-compose package.
Changes system state: review before running
docker --version docker compose version mkdir -p ~/gitea-script-catalog && cd ~/gitea-script-catalog
- Create a rootless Gitea Compose definition
Use the current stable rootless Gitea image and named volumes so Docker owns volume permissions. Bind the web port to localhost and let an internal reverse proxy provide HTTPS. Replace the example domain if you will use the service remotely.
Read-only command: verify target and scope
cat > compose.yaml <<'EOF' services: server: image: docker.gitea.com/gitea:1.27.1-rootless restart: unless-stopped environment: GITEA__server__DOMAIN: git.example.internal GITEA__server__ROOT_URL: https://git.example.internal/ volumes: - gitea-data:/var/lib/gitea - gitea-config:/etc/gitea ports: - "127.0.0.1:3000:3000" volumes: gitea-data: gitea-config: EOF docker compose config --quiet - Start Gitea and validate the local service
Start the container and confirm Gitea responds locally before configuring DNS, TLS, or repositories.
Changes system state: review before running
docker compose pull docker compose up -d docker compose ps curl -I http://127.0.0.1:3000/
- Complete the initial Gitea setup
Open the service through the intended internal HTTPS URL once the reverse proxy is configured. For this small Lab, use the built-in SQLite database, create the administrator account, and keep self-registration disabled unless you explicitly need it. Record the chosen site URL and data/config volume names as part of the Lab evidence.
- Create a private scripts repository
Create a repository such as ops-scripts, mark it private, and add a short description that states what kinds of scripts belong there. Avoid placing live passwords, API tokens, private keys, or unredacted production exports in the repository.
- Clone and initialize the catalog from a workstation
Clone over the HTTPS URL trusted by the workstation. Create a README and one harmless script, explicitly normalize the branch to main, then push the first commit.
Changes system state: review before running
git clone https://git.example.internal/<user>/ops-scripts.git cd ops-scripts printf '# Ops Scripts\n\nSmall reviewed scripts for the internal Lab catalog.\n' > README.md printf '#!/usr/bin/env bash\nprintf \"catalog validation\\n\"\n' > catalog-check.sh chmod +x catalog-check.sh git add README.md catalog-check.sh git commit -m 'Add initial catalog example' git branch -M main git push -u origin main
- Prove the repository is usable from a clean path
Clone the repository into a second temporary directory and run the harmless test script. This catches URL, authentication, certificate, repository visibility, and branch mistakes that the Gitea dashboard alone cannot prove.
Changes system state: review before running
cd .. git clone https://git.example.internal/<user>/ops-scripts.git ops-scripts-validation cd ops-scripts-validation git status --short --branch ./catalog-check.sh
- Record the persistent-state boundary
Gitea's repositories, database, secrets, and configuration live in the persistent data/config volumes, not in the disposable container image. Before upgrades or migration, back up those volumes according to your Docker/storage platform and preserve Gitea's generated security secrets with the configuration.
Validation
`docker compose ps` shows the Gitea service running and the local HTTP endpoint responds.
The internal HTTPS URL presents a trusted certificate when used from another workstation.
The `ops-scripts` repository is private and can be cloned by an authorized user.
A commit pushed to `main` appears in Gitea and a clean second clone can run the harmless validation script.
The operator can identify the Gitea data/config volumes that must be protected before upgrades or host replacement.
Troubleshooting
If Gitea starts but clients receive redirects to the wrong host or scheme, verify `GITEA__server__DOMAIN`, `GITEA__server__ROOT_URL`, and the reverse-proxy forwarding configuration before changing repository settings.
If HTTPS Git operations fail but the web UI works, inspect the workstation's certificate trust and the exact clone URL before weakening TLS verification.
Read-only command: verify target and scope
git remote -v curl -I https://git.example.internal/
If the container cannot write its storage, inspect the named volume/mount configuration and Gitea logs. Do not solve a volume problem with `chmod 777`.
Read-only command: verify target and scope
docker compose logs --tail=120 server docker volume ls | grep gitea
Cleanup or Rollback
Remove the temporary `ops-scripts-validation` clone after the Lab if it is not needed.
Stop the service with `docker compose down` when the Lab is not in use; do not add `-v` unless you deliberately intend to destroy the persistent repositories/configuration.
Before deleting the Lab, preserve a tested backup of the Gitea data/config volumes if the script catalog matters.
Next Improvements
Add repository templates, CODEOWNERS/review practices, or issue labels only after the basic clone/push workflow is stable.
Add scheduled backup and restore testing for Gitea persistent state.
Integrate CI only for scripts whose test and execution boundaries are understood.
