7.0 KiB
Single-VM deployment
The deployment is relocatable. Compose paths and management commands are
resolved relative to the repository checkout, so it can live anywhere on the
VM. /opt/idssys/TA-Deployment-Access is only one possible example.
One Compose project manages:
- TAPM broker, with an embedded SQLite database
- Gitea, with its own embedded SQLite database and repository storage
- Nginx, terminating TLS for the broker and Gitea
- Certbot, as an on-demand utility for certificate issuance and renewal
In production, only the configured Nginx HTTP and HTTPS ports are published.
They default to 8680 and 8643. Inside Docker, Nginx listens on ports 80 and 443,
the broker on 8080, and Gitea is explicitly pinned to 0.0.0.0:3000. Gitea
SSH is disabled. Deployment-level variables such as HTTP_PORT are not passed
into the Gitea container, preventing them from overriding its internal listener.
1. VM and network
Install Docker Engine with Compose v2. Permit the selected HTTP and HTTPS ports and forward public TCP 80 and 443 from the datacenter edge to them. The Create public DNS A/AAAA records for both application names before requesting the certificate.
Public port 80 must reach the container's port 80 for HTTP-01 certificate
renewal. For example, if HTTP_PORT=8080, the edge must forward public port 80
to VM port 8080. If IPv6 is published, it must reach this same VM.
2. Install the repository
sudo mkdir -p /YOUR/INSTALL/PARENT
sudo git clone GITEA-REPOSITORY-URL /YOUR/INSTALL/PARENT/TA-Deployment-Access
sudo chown -R 1000:1000 /YOUR/INSTALL/PARENT/TA-Deployment-Access
cd /YOUR/INSTALL/PARENT/TA-Deployment-Access
cp .env.example .env
chmod 600 .env
Set BROKER_DOMAIN, GITEA_DOMAIN, and LETSENCRYPT_EMAIL first. HTTP_PORT
and HTTPS_PORT control the VM-side Docker bindings and default to 8680 and
8643. The datacenter edge should therefore forward public ports 80 and 443 to
VM ports 8680 and 8643. Replace all example domains in the TAPM variables.
Generate the cookie secret with:
openssl rand -base64 48
Runtime state is deliberately visible below the checkout:
config/
├── broker/ # tapm.db and SQLite WAL files
├── gitea/
│ ├── config/ # app.ini and Gitea configuration
│ └── data/ # repositories, packages, and gitea.db
├── letsencrypt/ # account data, certificate, and private key
├── ssl/ # optional administrator-provided certificate
├── certbot-webroot/ # HTTP-01 challenge files
└── backups/ # local offline snapshots
The contents are ignored by Git. They must never be committed.
3. Bootstrap Gitea and TLS
./manage.sh bootstrap
This prepares the runtime directories, creates the private Docker network, starts Gitea and the HTTP-only Nginx configuration, obtains a certificate when using Let's Encrypt, and switches Nginx to TLS.
For an administrator-provided certificate instead, place the certificate and
key in config/ssl/ and set:
SSL_MODE=custom
SSL_CERTIFICATE_DIR=./config/ssl
SSL_CERTIFICATE_FILE=fullchain.pem
SSL_CERTIFICATE_KEY_FILE=privkey.pem
The certificate must cover both BROKER_DOMAIN and GITEA_DOMAIN. With custom
mode, bootstrap skips Certbot and renew is intentionally unavailable;
replace the files through the certificate provider's process and restart or
reload Nginx. SSL_CERTIFICATE_DIR can point at another directory relative to
the repository or at an absolute host path.
Create the initial Gitea administrator:
./manage.sh create-admin
No Gitea login is hard-coded or stored in .env. The command prompts for the
administrator username and email, generates a temporary password, and requires
it to be changed at first login. The initial web installer is intentionally
locked and public registration is disabled.
Sign in to Gitea at https://GITEA_DOMAIN, create the TAI organization, and
create:
tapm-packages, with a read-only package token.tapm-publisher, with a write package token.- An OAuth2 application whose callback is
https://BROKER_DOMAIN/auth/callback.
Place those token and OAuth values in .env. The broker cannot start until all
required credentials are present.
4. Start the complete deployment
./manage.sh start
./manage.sh status
curl --fail "https://BROKER_DOMAIN/health/ready"
curl --fail "https://GITEA_DOMAIN/api/healthz"
The broker automatically applies SQLite schema migrations before starting.
Gitea uses its own SQLite database at
config/gitea/data/data/gitea.db.
For local testing that bypasses Nginx, set BROKER_DIRECT_PORT and
GITEA_DIRECT_PORT in .env. Set GITEA_DIRECT_ROOT_URL to the exact URL the
test browser will use, including the VM hostname or IP address and port:
BROKER_DIRECT_PORT=8080
GITEA_DIRECT_PORT=3000
GITEA_DIRECT_ROOT_URL=http://192.0.2.10:3000/
Then run:
./manage.sh start-direct
This adds host mappings to the broker's port 8080 and Gitea's port 3000. It also changes Gitea's root URL and session cookie policy to permit HTTP login. The direct broker port is suitable for health and API testing; technician OAuth login remains designed for the HTTPS public URL. Do not use the direct-port override on an Internet-facing production VM. Return to the production URL and secure-cookie policy with:
./manage.sh start
docker compose -f compose.yaml -f compose.tls.yaml up -d --force-recreate broker gitea
5. Move repositories
For each existing repository, create an empty matching repository in the new Gitea and mirror all refs:
git clone --mirror OLD-REPOSITORY-URL
cd REPOSITORY.git
git push --mirror https://GITEA_DOMAIN/TAI/REPOSITORY.git
Update developer remotes, CI credentials, submodules, documentation, and the Go module path only if the hostname embedded in the module path is also changing. Move the deployment repository last so this checkout remains updateable during the transition.
6. Renewal and backups
When SSL_MODE=letsencrypt, run renewal twice daily from root's crontab:
17 3,15 * * * cd /YOUR/INSTALL/PARENT/TA-Deployment-Access && ./manage.sh renew
Create an application-consistent local snapshot with:
./manage.sh backup
The backup briefly stops both SQLite writers. Copy config/backups/ to storage
outside the VM. A backup left only on this VM does not protect against VM or
datacenter loss. Also back up .env through a secrets-aware system.
7. Updates
cd /YOUR/INSTALL/PARENT/TA-Deployment-Access
./update.sh
The updater operates only on the current VM. It fast-forwards the checked-out
branch, pulls the pinned Gitea and Nginx images, rebuilds and restarts the local
stack, and waits for the local broker to become healthy. Certbot is not pulled
or run during a routine update; it is used only by bootstrap and renew. The
updater has no peer discovery, SSH, or multi-node update behavior.
Pin image versions as supplied and review release notes before changing them. Never change Gitea between rootless and rootful image families in place.