chore: bootstrap Atay Makhzan ops repo
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
# Copy to .env on the VPS and fill real values there.
|
||||
# Never commit the real .env file.
|
||||
|
||||
GITEA_VERSION=1.26.2
|
||||
POSTGRES_VERSION=16-alpine
|
||||
|
||||
GITEA_DOMAIN=ataymakhzan.com
|
||||
GITEA_SSH_DOMAIN=ataymakhzan.com
|
||||
GITEA_ROOT_URL=https://ataymakhzan.com/
|
||||
GITEA_HTTP_PORT=3001
|
||||
GITEA_HTTP_BIND=127.0.0.1
|
||||
GITEA_SSH_PORT=2222
|
||||
|
||||
GITEA_USER_UID=1000
|
||||
GITEA_USER_GID=1000
|
||||
|
||||
POSTGRES_DB=gitea
|
||||
POSTGRES_USER=gitea
|
||||
POSTGRES_PASSWORD=change-me-before-deploy
|
||||
|
||||
GITEA_CONTAINER_NAME=gitea
|
||||
POSTGRES_CONTAINER_NAME=gitea-db
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
# Secrets
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
app.ini
|
||||
*.pem
|
||||
*.key
|
||||
*.crt
|
||||
id_rsa*
|
||||
id_ed25519*
|
||||
*_token*
|
||||
*secret*
|
||||
|
||||
# Backups and dumps
|
||||
backups/
|
||||
*.dump
|
||||
*.sql
|
||||
*.sqlite
|
||||
*.zip
|
||||
*.tar
|
||||
*.tar.gz
|
||||
*.tgz
|
||||
|
||||
# Runtime data
|
||||
gitea-data/
|
||||
postgres-data/
|
||||
log/
|
||||
logs/
|
||||
|
||||
# Local/editor
|
||||
.DS_Store
|
||||
.idea/
|
||||
.vscode/
|
||||
*.swp
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026 Saad ibn Zoubayr
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,82 @@
|
||||
# Atay Makhzan Ops
|
||||
|
||||
Open-source operations repository for **Atay Makhzan**, Saad ibn Zoubayr's self-hosted Gitea forge.
|
||||
|
||||
Atay Makhzan is currently a sovereign Git forge running Gitea on a VPS with Docker Compose, PostgreSQL, Nginx, and SSH Git access.
|
||||
|
||||
## Current production snapshot
|
||||
|
||||
| Area | Current value |
|
||||
|---|---|
|
||||
| Public domain | `ataymakhzan.com` |
|
||||
| Forge | Gitea |
|
||||
| Gitea image | `gitea/gitea:1.26.2` |
|
||||
| Database | PostgreSQL via `postgres:16-alpine` |
|
||||
| Stack path | `/opt/gitea` |
|
||||
| Web proxy | Nginx + Certbot TLS |
|
||||
| Local Gitea HTTP | `127.0.0.1:3001` / container port `3001` |
|
||||
| Git SSH | `ataymakhzan.com:2222` |
|
||||
|
||||
## What belongs in this repo
|
||||
|
||||
- Sanitized Docker Compose templates
|
||||
- Nginx reverse-proxy templates
|
||||
- Backup, verification, and upgrade scripts
|
||||
- Restore and maintenance runbooks
|
||||
- Architecture decision records
|
||||
- Public roadmap for future Atay Makhzan evolution
|
||||
|
||||
## What must never be committed
|
||||
|
||||
- `.env` with real secrets
|
||||
- Gitea `app.ini` with secrets
|
||||
- PostgreSQL passwords
|
||||
- SSH private keys
|
||||
- Gitea dumps or database dumps
|
||||
- Repository backups
|
||||
- API tokens or access tokens
|
||||
- TLS private keys
|
||||
|
||||
See [`SECURITY.md`](SECURITY.md).
|
||||
|
||||
## Quick commands
|
||||
|
||||
Verify a live instance:
|
||||
|
||||
```bash
|
||||
DOMAIN=ataymakhzan.com \
|
||||
SSH_PORT=2222 \
|
||||
OWNER=ibnezzoubayr \
|
||||
PROBE_REPO=Empire-OS \
|
||||
./scripts/verify-gitea.sh
|
||||
```
|
||||
|
||||
Create a rollback backup on the VPS:
|
||||
|
||||
```bash
|
||||
sudo STACK_DIR=/opt/gitea ./scripts/backup-gitea.sh
|
||||
```
|
||||
|
||||
Prepare an upgrade dry-run:
|
||||
|
||||
```bash
|
||||
sudo TARGET_VERSION=1.26.2 STACK_DIR=/opt/gitea ./scripts/upgrade-gitea.sh
|
||||
```
|
||||
|
||||
Apply an upgrade intentionally:
|
||||
|
||||
```bash
|
||||
sudo TARGET_VERSION=1.26.2 STACK_DIR=/opt/gitea APPLY=1 ./scripts/upgrade-gitea.sh
|
||||
```
|
||||
|
||||
## Strategic direction
|
||||
|
||||
This repo starts as **ops/infrastructure** for the official Gitea-based Atay Makhzan deployment.
|
||||
|
||||
Later, if Atay Makhzan needs product behavior that Gitea cannot cleanly support through configuration, themes, plugins, or external automation, we can create a separate source fork and maintain it as its own product.
|
||||
|
||||
Until then, the CTO rule is:
|
||||
|
||||
> Do not fork Gitea prematurely. First make the deployment reproducible, observable, backed up, and safe to upgrade.
|
||||
|
||||
See [`docs/FUTURE-GITEA-FORK.md`](docs/FUTURE-GITEA-FORK.md).
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
# Security Policy
|
||||
|
||||
This repository is public. Treat it as documentation and reproducible operations code, not as a secret store.
|
||||
|
||||
## Never commit
|
||||
|
||||
- Real `.env` files
|
||||
- Gitea `app.ini` secrets
|
||||
- Database passwords
|
||||
- SMTP credentials
|
||||
- OAuth secrets
|
||||
- SSH private keys
|
||||
- API tokens
|
||||
- Gitea dump archives
|
||||
- PostgreSQL dump files
|
||||
- TLS private keys
|
||||
- Full production logs containing sensitive data
|
||||
|
||||
## Safe to commit
|
||||
|
||||
- `.env.example` with placeholders
|
||||
- Docker Compose templates with variable references
|
||||
- Nginx templates without private keys
|
||||
- Runbooks
|
||||
- Scripts that read secrets from the environment
|
||||
- Architecture records
|
||||
|
||||
## If a secret is committed
|
||||
|
||||
1. Rotate the secret immediately.
|
||||
2. Remove it from current files.
|
||||
3. Rewrite public Git history only if the exposure is severe and worth the operational risk.
|
||||
4. Assume the secret was copied by someone else.
|
||||
|
||||
## Operational rule
|
||||
|
||||
For production maintenance, create backups before upgrades and verify both web and SSH Git paths after changes.
|
||||
@@ -0,0 +1,38 @@
|
||||
services:
|
||||
server:
|
||||
image: gitea/gitea:${GITEA_VERSION:-1.26.2}
|
||||
container_name: ${GITEA_CONTAINER_NAME:-gitea}
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- USER_UID=${GITEA_USER_UID:-1000}
|
||||
- USER_GID=${GITEA_USER_GID:-1000}
|
||||
- GITEA__database__DB_TYPE=postgres
|
||||
- GITEA__database__HOST=db:5432
|
||||
- GITEA__database__NAME=${POSTGRES_DB:-gitea}
|
||||
- GITEA__database__USER=${POSTGRES_USER:-gitea}
|
||||
- GITEA__database__PASSWD=${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD}
|
||||
- GITEA__server__DOMAIN=${GITEA_DOMAIN:-ataymakhzan.com}
|
||||
- GITEA__server__SSH_DOMAIN=${GITEA_SSH_DOMAIN:-ataymakhzan.com}
|
||||
- GITEA__server__ROOT_URL=${GITEA_ROOT_URL:-https://ataymakhzan.com/}
|
||||
- GITEA__server__HTTP_PORT=${GITEA_HTTP_PORT:-3001}
|
||||
- GITEA__server__SSH_PORT=${GITEA_SSH_PORT:-2222}
|
||||
volumes:
|
||||
- ./gitea-data:/data
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
ports:
|
||||
- "${GITEA_HTTP_BIND:-127.0.0.1}:${GITEA_HTTP_PORT:-3001}:${GITEA_HTTP_PORT:-3001}"
|
||||
- "${GITEA_SSH_PORT:-2222}:22"
|
||||
depends_on:
|
||||
- db
|
||||
|
||||
db:
|
||||
image: postgres:${POSTGRES_VERSION:-16-alpine}
|
||||
container_name: ${POSTGRES_CONTAINER_NAME:-gitea-db}
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- POSTGRES_DB=${POSTGRES_DB:-gitea}
|
||||
- POSTGRES_USER=${POSTGRES_USER:-gitea}
|
||||
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD}
|
||||
volumes:
|
||||
- ./postgres-data:/var/lib/postgresql/data
|
||||
@@ -0,0 +1,49 @@
|
||||
# ADR-0001: Current Gitea Docker Compose Architecture
|
||||
|
||||
## Status
|
||||
|
||||
Accepted.
|
||||
|
||||
## Context
|
||||
|
||||
Atay Makhzan needs a sovereign Git forge controlled by Saad ibn Zoubayr. The current operational need is reliability, simple maintenance, backups, and controlled upgrades.
|
||||
|
||||
## Decision
|
||||
|
||||
Run official Gitea in Docker Compose with PostgreSQL, reverse-proxied by Nginx with Certbot TLS.
|
||||
|
||||
Current production shape:
|
||||
|
||||
- Gitea image pinned to `gitea/gitea:1.26.2`
|
||||
- PostgreSQL image `postgres:16-alpine`
|
||||
- Gitea HTTP served locally on port `3001`
|
||||
- Public HTTPS via Nginx on `ataymakhzan.com`
|
||||
- Git SSH exposed on port `2222`
|
||||
- Persistent data mounted under `/opt/gitea`
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
|
||||
- Simple architecture
|
||||
- Easy backups
|
||||
- Easy rollback through Docker image pinning and database dumps
|
||||
- Low operational burden
|
||||
- Enough for current private forge needs
|
||||
|
||||
### Negative
|
||||
|
||||
- Single VPS is a single point of failure
|
||||
- Scaling and HA are manual future work
|
||||
- Public customization is limited unless we theme, extend, or fork
|
||||
- Production safety depends on disciplined backups and upgrade procedure
|
||||
|
||||
## Future trigger for revisiting
|
||||
|
||||
Revisit this decision if Atay Makhzan needs:
|
||||
|
||||
- Multi-node availability
|
||||
- Custom product features inside the forge
|
||||
- Organization-wide policy automation not available in Gitea
|
||||
- Deep UI/UX changes that themes cannot support
|
||||
- Integrated CI/package registry workflows beyond Gitea's native capabilities
|
||||
@@ -0,0 +1,60 @@
|
||||
# Future Gitea Fork Strategy
|
||||
|
||||
Saad's long-term intent is valid: Atay Makhzan may eventually differ enough from upstream Gitea that we maintain our own source code separately.
|
||||
|
||||
But the sequencing matters.
|
||||
|
||||
## CTO verdict
|
||||
|
||||
Do not fork Gitea just because we can.
|
||||
|
||||
Fork only when one of these is true:
|
||||
|
||||
1. The required feature cannot be achieved with configuration.
|
||||
2. It cannot be achieved cleanly with Gitea Actions, webhooks, external automation, or themes.
|
||||
3. The feature is core to Atay Makhzan's identity as a product.
|
||||
4. Maintaining the patch is cheaper than working around upstream.
|
||||
5. We have time to track upstream security releases and merge conflicts.
|
||||
|
||||
## Recommended stages
|
||||
|
||||
### Stage 1 — Ops sovereignty
|
||||
|
||||
This repository.
|
||||
|
||||
Goal: make deployment reproducible, documented, backed up, and safe to upgrade.
|
||||
|
||||
### Stage 2 — External extensions
|
||||
|
||||
Use webhooks, scripts, bots, custom templates, and integrations around Gitea without touching upstream source.
|
||||
|
||||
### Stage 3 — Theming and UX identity
|
||||
|
||||
Customize branding, templates, and public surfaces while remaining close to upstream.
|
||||
|
||||
### Stage 4 — Source fork
|
||||
|
||||
Create a dedicated source repository only when Atay Makhzan needs product behavior that upstream Gitea will not support.
|
||||
|
||||
Suggested future repo name:
|
||||
|
||||
```text
|
||||
ibnezzoubayr/Atay-Makhzan
|
||||
```
|
||||
|
||||
This ops repo should remain separate:
|
||||
|
||||
```text
|
||||
ibnezzoubayr/Atay-Makhzan-Ops
|
||||
```
|
||||
|
||||
## Fork discipline
|
||||
|
||||
If we fork:
|
||||
|
||||
- Track upstream Gitea releases.
|
||||
- Keep a changelog of every divergence.
|
||||
- Keep custom patches small and isolated.
|
||||
- Add tests for every custom behavior.
|
||||
- Maintain an upstream merge schedule.
|
||||
- Never delay critical upstream security patches for cosmetic customization.
|
||||
@@ -0,0 +1,32 @@
|
||||
# Restore Notes
|
||||
|
||||
Restoring Atay Makhzan can destroy or overwrite live data. Do not run restore actions without explicit owner approval.
|
||||
|
||||
## Backup artifacts expected
|
||||
|
||||
A complete backup directory should contain:
|
||||
|
||||
- `gitea-dump-<timestamp>.zip`
|
||||
- `gitea-postgres-<timestamp>.dump`
|
||||
- `docker-compose.yml`
|
||||
- `app.ini`
|
||||
- `metadata.txt`
|
||||
- `SHA256SUMS`
|
||||
|
||||
## Safer restore principle
|
||||
|
||||
Prefer restoring to a fresh VPS or staging directory first, then verifying repository data before touching production.
|
||||
|
||||
## High-level restore sequence
|
||||
|
||||
1. Provision VPS and install Docker/Nginx.
|
||||
2. Restore sanitized Compose configuration.
|
||||
3. Restore PostgreSQL dump into a fresh database.
|
||||
4. Restore Gitea data from Gitea dump according to the Gitea version documentation.
|
||||
5. Start containers.
|
||||
6. Verify API, web, SSH auth, and `git ls-remote` on known repositories.
|
||||
7. Switch DNS/proxy only after verification.
|
||||
|
||||
## Production warning
|
||||
|
||||
Do not remove `/opt/gitea/gitea-data` or `/opt/gitea/postgres-data` unless a verified backup exists and Saad explicitly approved the restore.
|
||||
@@ -0,0 +1,71 @@
|
||||
# Atay Makhzan Runbook
|
||||
|
||||
## Deployment shape
|
||||
|
||||
Atay Makhzan currently runs as a Docker Compose stack on a VPS:
|
||||
|
||||
- Stack directory: `/opt/gitea`
|
||||
- Gitea container: `gitea`
|
||||
- PostgreSQL container: `gitea-db`
|
||||
- Public HTTPS: `https://ataymakhzan.com`
|
||||
- Local Gitea HTTP: `http://127.0.0.1:3001`
|
||||
- Git SSH: `ssh://git@ataymakhzan.com:2222/<owner>/<repo>.git`
|
||||
|
||||
## Normal health check
|
||||
|
||||
From the VPS:
|
||||
|
||||
```bash
|
||||
cd /opt/gitea
|
||||
docker compose ps
|
||||
curl -fsS http://127.0.0.1:3001/api/v1/version
|
||||
docker exec -u git gitea gitea doctor check -c /data/gitea/conf/app.ini -w /data/gitea
|
||||
```
|
||||
|
||||
From outside:
|
||||
|
||||
```bash
|
||||
curl -fsS https://ataymakhzan.com/api/v1/version
|
||||
ssh -p 2222 -o BatchMode=yes -T git@ataymakhzan.com
|
||||
git ls-remote --heads ssh://git@ataymakhzan.com:2222/ibnezzoubayr/Empire-OS.git
|
||||
```
|
||||
|
||||
## Backup before maintenance
|
||||
|
||||
```bash
|
||||
sudo STACK_DIR=/opt/gitea ./scripts/backup-gitea.sh
|
||||
```
|
||||
|
||||
A proper backup should include:
|
||||
|
||||
- Gitea built-in dump
|
||||
- PostgreSQL `pg_dump -Fc`
|
||||
- `docker-compose.yml`
|
||||
- `app.ini`
|
||||
- metadata and checksums
|
||||
|
||||
## Upgrade policy
|
||||
|
||||
1. Inspect current state.
|
||||
2. Create backup.
|
||||
3. Pull target image.
|
||||
4. Pin explicit Gitea version in Compose.
|
||||
5. Recreate only the Gitea service.
|
||||
6. Verify web, API, SSH, `git ls-remote`, and doctor check.
|
||||
|
||||
Do not run production on `gitea/gitea:latest`.
|
||||
|
||||
## Rollback policy
|
||||
|
||||
Rollback can involve code image rollback, config rollback, or database restore.
|
||||
|
||||
- Re-tagged Docker images are low-risk.
|
||||
- Restoring database dumps is destructive and requires explicit owner approval.
|
||||
- Never delete volumes during an emergency unless a verified backup exists.
|
||||
|
||||
## Routine cleanup candidates
|
||||
|
||||
- Remove obsolete Compose `version:` key from the live stack.
|
||||
- Move deprecated Gitea `[picture]` options out of `app.ini` if still present.
|
||||
- Add backup retention and offsite backup storage.
|
||||
- Add uptime/health monitoring.
|
||||
@@ -0,0 +1,38 @@
|
||||
# Nginx reverse proxy template for Atay Makhzan / Gitea.
|
||||
# Replace DOMAIN and local port values if they differ.
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name ataymakhzan.com www.ataymakhzan.com;
|
||||
|
||||
location /.well-known/acme-challenge/ {
|
||||
root /var/www/html;
|
||||
}
|
||||
|
||||
location / {
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name ataymakhzan.com www.ataymakhzan.com;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/ataymakhzan.com/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/ataymakhzan.com/privkey.pem;
|
||||
|
||||
client_max_body_size 512M;
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:3001;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_set_header X-Forwarded-Port 443;
|
||||
|
||||
proxy_read_timeout 300s;
|
||||
proxy_send_timeout 300s;
|
||||
}
|
||||
}
|
||||
Executable
+45
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
STACK_DIR="${STACK_DIR:-/opt/gitea}"
|
||||
GITEA_CONTAINER="${GITEA_CONTAINER:-gitea}"
|
||||
DB_CONTAINER="${DB_CONTAINER:-gitea-db}"
|
||||
POSTGRES_USER="${POSTGRES_USER:-gitea}"
|
||||
POSTGRES_DB="${POSTGRES_DB:-gitea}"
|
||||
|
||||
cd "$STACK_DIR"
|
||||
TS="$(date -u +%Y%m%d-%H%M%S)"
|
||||
BK="$STACK_DIR/backups/$TS"
|
||||
mkdir -p "$BK"
|
||||
|
||||
cp docker-compose.yml "$BK/docker-compose.yml"
|
||||
if [ -f "$STACK_DIR/gitea-data/gitea/conf/app.ini" ]; then
|
||||
cp "$STACK_DIR/gitea-data/gitea/conf/app.ini" "$BK/app.ini"
|
||||
fi
|
||||
|
||||
{
|
||||
echo "backup_utc=$TS"
|
||||
echo "host=$(hostname)"
|
||||
echo "date=$(date -u --iso-8601=seconds)"
|
||||
echo "docker=$(docker --version)"
|
||||
echo "compose=$(docker compose version 2>/dev/null || true)"
|
||||
echo "gitea_version=$(docker exec -u git "$GITEA_CONTAINER" gitea --version 2>/dev/null || true)"
|
||||
docker ps --format '{{.Names}} | {{.Image}} | {{.Status}} | {{.Ports}}'
|
||||
} > "$BK/metadata.txt"
|
||||
|
||||
docker exec -u git "$GITEA_CONTAINER" mkdir -p /data/gitea/backup-tmp
|
||||
DUMP_NAME="gitea-dump-$TS.zip"
|
||||
docker exec -u git "$GITEA_CONTAINER" gitea dump \
|
||||
-c /data/gitea/conf/app.ini \
|
||||
-w /data/gitea \
|
||||
-f "/data/gitea/backup-tmp/$DUMP_NAME" \
|
||||
--quiet
|
||||
|
||||
cp "$STACK_DIR/gitea-data/gitea/backup-tmp/$DUMP_NAME" "$BK/$DUMP_NAME"
|
||||
rm -f "$STACK_DIR/gitea-data/gitea/backup-tmp/$DUMP_NAME"
|
||||
|
||||
docker exec "$DB_CONTAINER" pg_dump -U "$POSTGRES_USER" -d "$POSTGRES_DB" -Fc > "$BK/gitea-postgres-$TS.dump"
|
||||
sha256sum "$BK"/* > "$BK/SHA256SUMS"
|
||||
|
||||
echo "Backup created: $BK"
|
||||
du -sh "$BK" "$BK"/*
|
||||
Executable
+68
@@ -0,0 +1,68 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
STACK_DIR="${STACK_DIR:-/opt/gitea}"
|
||||
TARGET_VERSION="${TARGET_VERSION:?set TARGET_VERSION, e.g. TARGET_VERSION=1.26.2}"
|
||||
GITEA_CONTAINER="${GITEA_CONTAINER:-gitea}"
|
||||
APPLY="${APPLY:-0}"
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
cd "$STACK_DIR"
|
||||
|
||||
if [ ! -f docker-compose.yml ]; then
|
||||
echo "docker-compose.yml not found in $STACK_DIR" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "== Current version =="
|
||||
docker exec -u git "$GITEA_CONTAINER" gitea --version || true
|
||||
|
||||
echo "== Creating backup first =="
|
||||
"$SCRIPT_DIR/backup-gitea.sh"
|
||||
|
||||
echo "== Pulling target image =="
|
||||
docker pull "gitea/gitea:$TARGET_VERSION"
|
||||
docker run --rm --user git --entrypoint /usr/local/bin/gitea "gitea/gitea:$TARGET_VERSION" --version || true
|
||||
|
||||
OLD_IMAGE_ID="$(docker image inspect "$(docker inspect --format '{{.Config.Image}}' "$GITEA_CONTAINER")" --format '{{.Id}}' 2>/dev/null || true)"
|
||||
if [ -n "$OLD_IMAGE_ID" ]; then
|
||||
ROLLBACK_TAG="gitea/gitea:rollback-$(date -u +%Y%m%d-%H%M%S)"
|
||||
docker tag "$OLD_IMAGE_ID" "$ROLLBACK_TAG"
|
||||
echo "Rollback image tag: $ROLLBACK_TAG"
|
||||
fi
|
||||
|
||||
echo "== Pinning docker-compose.yml to target version =="
|
||||
python3 - <<PY
|
||||
from pathlib import Path
|
||||
import re
|
||||
p = Path('$STACK_DIR/docker-compose.yml')
|
||||
s = p.read_text()
|
||||
s2 = re.sub(r'image:\s*gitea/gitea:[^\s]+', 'image: gitea/gitea:$TARGET_VERSION', s, count=1)
|
||||
if s2 == s:
|
||||
raise SystemExit('Could not find gitea/gitea image line to replace')
|
||||
p.write_text(s2)
|
||||
PY
|
||||
|
||||
docker compose config >/dev/null
|
||||
|
||||
if [ "$APPLY" != "1" ]; then
|
||||
echo "Dry-run complete. Compose file was pinned, but service was not recreated."
|
||||
echo "Review the diff, then run with APPLY=1 to recreate the Gitea service."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "== Recreating Gitea service only =="
|
||||
docker compose up -d server
|
||||
|
||||
echo "== Waiting for readiness =="
|
||||
for _ in $(seq 1 90); do
|
||||
if curl -fsS "http://127.0.0.1:3001/api/v1/version" | grep -q "$TARGET_VERSION"; then
|
||||
echo
|
||||
echo "Gitea $TARGET_VERSION is ready."
|
||||
exit 0
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
|
||||
echo "Gitea did not report target version in time" >&2
|
||||
exit 1
|
||||
Executable
+42
@@ -0,0 +1,42 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
DOMAIN="${DOMAIN:-ataymakhzan.com}"
|
||||
SSH_PORT="${SSH_PORT:-2222}"
|
||||
OWNER="${OWNER:-ibnezzoubayr}"
|
||||
PROBE_REPO="${PROBE_REPO:-Empire-OS}"
|
||||
LOCAL_URL="${LOCAL_URL:-http://127.0.0.1:3001}"
|
||||
GITEA_CONTAINER="${GITEA_CONTAINER:-gitea}"
|
||||
RUN_DOCKER_CHECKS="${RUN_DOCKER_CHECKS:-1}"
|
||||
|
||||
echo "== Local API version =="
|
||||
curl -fsS "$LOCAL_URL/api/v1/version"
|
||||
echo
|
||||
|
||||
echo "== External API version =="
|
||||
curl -fsS "https://$DOMAIN/api/v1/version"
|
||||
echo
|
||||
|
||||
echo "== External homepage status =="
|
||||
curl -fsS -I -L --max-time 20 "https://$DOMAIN/" | sed -n '1,12p'
|
||||
|
||||
echo "== Git SSH authentication =="
|
||||
SSH_OUT=$(ssh -p "$SSH_PORT" -o BatchMode=yes -o ConnectTimeout=10 -T "git@$DOMAIN" 2>&1 || true)
|
||||
echo "$SSH_OUT"
|
||||
echo "$SSH_OUT" | grep -Eiq 'successfully authenticated|Hi .*!|Welcome' || {
|
||||
echo "Could not confirm successful SSH authentication from output" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo "== Git ls-remote probe =="
|
||||
git ls-remote --heads "ssh://git@$DOMAIN:$SSH_PORT/$OWNER/$PROBE_REPO.git" >/dev/null
|
||||
|
||||
echo "== Optional Docker/native checks =="
|
||||
if [ "$RUN_DOCKER_CHECKS" = "1" ] && command -v docker >/dev/null 2>&1; then
|
||||
docker exec -u git "$GITEA_CONTAINER" gitea --version
|
||||
docker exec -u git "$GITEA_CONTAINER" gitea doctor check -c /data/gitea/conf/app.ini -w /data/gitea
|
||||
else
|
||||
echo "Skipping Docker checks. Set RUN_DOCKER_CHECKS=1 on the VPS to enable."
|
||||
fi
|
||||
|
||||
echo "Atay Makhzan verification passed."
|
||||
Reference in New Issue
Block a user