---
title: Mentés
url: 'https://wiki.teletypegames.org/hu/infrastructure/backup'
markdown: 'https://wiki.teletypegames.org/hu/infrastructure/backup.md'
lang: hu
date: '2026-09-14'
description: 'Két lánc: egy Makefile-alapú mentés az adatbázis-dumpokhoz és a Gitea-repók tükréhez, utána egy rsync-alapú teljes állomány-tükör egy távoli NAS-ra. 2026-10-16 óta ez a rend. Előtte a második lánc restic volt, ezt kivezettük: a mentés egyszerűbb lett, cserébe nincs verziózás. Napi menetrend Id…'
taxonomy:
  tag:
    - howto
---

# Mentés

> Két lánc: egy Makefile-alapú mentés az adatbázis-dumpokhoz és a Gitea-repók tükréhez, utána egy rsync-alapú teljes állomány-tükör egy távoli NAS-ra. 2026-10-16 óta ez a rend. Előtte a második lánc restic volt, ezt kivezettük: a mentés egyszerűbb lett, cserébe nincs verziózás.

# Napi menetrend

| Idő | Mi | Eszköz |
|---|---|---|
| 04:00 | Redmine (MariaDB), katalógus és Gitea (MySQL) dump → minden Gitea-repó tükrözése → 7 napnál régebbi dumpok törlése | `make backup` (cron, `infra/backup-scripts`) |
| 05:00 | Matomo, ResourceSpace és Uptime Kuma dump → Woodpecker és Grafana SQLite-másolat → csomaglista → teljes állomány-tükör a NAS-ra | `vps-backup-sync` (systemd timer, `infra/host-config`) |

A tükör azért fut egy órával később, hogy a friss dumpokat és repótükröket is vigye. A 04:00-s lánc nem szinkronizál külön, a NAS-ra minden a 05:00-s tükörrel megy át.

# 1. lánc: dumpok és repótükrök (Makefile)

Környezeti változók a `Makefile`-ban:

| Változó | Jelentés |
|---|---|
| `BACKUP_BASE` | Minden mentés gyökere (alapérték `/srv/backup`) |
| `BACKUP_KEEP_DAYS` | Az adatbázisdumpok megőrzési ideje (alapérték `7`) |
| `DATABASE_BACKUP_BASE` | Ide kerülnek az SQL-dumpok |
| `REPOSITORY_BACKUP_BASE` | Ide kerülnek a tükrözött repók |
| `GITEA_SERVER`, `GITEA_TOKEN` | Gitea API a repók listázásához; a token egy `.envrc` fájlból jön, amit a Makefile maga olvas be (`-include`), így cron alatt is működik |

## Célok

```bash
make backup                          # db_redmine -> db_catalog -> db_gitea -> repos -> db_cleanup
make db_redmine db_catalog db_gitea  # csak az adatbázisok
make repos                           # a git-tükrök frissítése
make db_cleanup                      # a lejárt dumpok törlése
```

## Adatbázismentések

Minden dump a szolgáltatás konténerén belül fut. A dumpok időbélyeggel a konténer `/db_backup` könyvtárába kerülnek, amely a hoszt `DATABASE_BACKUP_BASE` könyvtárára van csatolva.

| Szolgáltatás | Hogyan | Megjegyzés |
|---|---|---|
| Redmine (MariaDB) | `database/mariadb_backup.sh` | `MARIADB_USER`, `MARIADB_PASSWORD`, `MARIADB_DATABASE` a konténerben |
| Katalógus (MySQL, `softwares`) | `database/mysql_backup.sh` | `MYSQL_ROOT_PASSWORD`, `MYSQL_DATABASE` a konténerben |
| Gitea (MySQL, `gitea`) | `db_gitea` a Makefile-ban: `mysqldump --single-transaction --routines --triggers` | **2026-10-16 óta.** Előtte a Gitea adatbázisa (felhasználók, jogosultságok, issue-k, PR-ek, OAuth-alkalmazások, registry-metaadatok) sehol nem volt mentve. |
| Wiki (PostgreSQL) | `database/pg_backup.sh` | **Kivezetve 2026-09-11** – a Wiki.js adatbázisa megszűnt, a szkript csak örökség. |

## Repómentések

A `make repos` a Gitea API-ból kilistázza az összes privát és publikus repót, majd repónként: `fetch --all --prune` + `pull`, ha helyben már megvan, `git clone`, ha még nincs.

## Takarítás

A `make db_cleanup` adatbázis-előtag szerint csoportosítja a dumpokat, és törli a `BACKUP_KEEP_DAYS`-nél régebbi fájlokat. Egy biztonsági ellenőrzés adatbázisonként legalább egy mentést mindig meghagy, akkor is, ha az régebbi a megőrzési ablaknál.

# 2. lánc: állomány-tükör (vps-backup-sync)

A `/usr/local/sbin/vps-backup-sync` szkript (forrása az `infra/host-config` repóban) rootként fut a `vps-backup-sync.timer` indítására.

**Dumpok a szkript elején:** Matomo (`mariadb-dump`), ResourceSpace (`--all-databases`), Uptime Kuma (`sqlite3 .backup`). A futó Woodpecker és Grafana SQLite-adatbázisról `sqlite3 .backup` készít konzisztens másolatot a fájl mellé (`woodpecker-backup.sqlite`, `grafana-backup.db`). A telepített csomagok listája a `/srv/backup/system/` alá kerül (`dpkg --get-selections`, `apt-mark showmanual`).

**Mit tükröz:** a `/srv/stacks`, `/srv/stacks_disabled`, `/srv/backup`, `/srv/host-config`, `/srv/presentation`, `/srv/dockge` könyvtárat, a hoszt `/etc`, `/root`, `/home`, `/usr/local/sbin`, `/var/spool/cron` és `/var/www` könyvtárát, valamint a ResourceSpace fájltár és a Matomo Docker-volume-ját. Összesen kb. 27 GB.

**Mit nem:** az élő adatbázis-könyvtárakat (helyettük a dumpok, mert egy futó DB fájljai nem konzisztensek), `node_modules`, `tmp`, `log`, Gitea keresőindexek, cache-ek.

**Hogyan:** `rsync -aH --numeric-ids --relative --delete` a NAS egy 700-as jogosultságú könyvtárába, abszolút útvonalakkal. A NAS-on egy nem-root felhasználó fogad, ezért a tulajdonos, a jogosultság és az eszközadat xattr-ban tárolódik (`-M--fake-super`). Visszafelé is ezzel a kapcsolóval kell másolni, különben minden fájl a NAS-felhasználóé lesz.

**Verziózás nincs.** A NAS-on mindig a legutóbbi állapot van. Ha valami törlődik vagy elromlik a szerveren, a következő éjjel a NAS-on is törlődik vagy elromlik. Az adatbázisoknál a 7 napos dump-rotáció ad némi visszamenőleges védelmet.

# Távoli tükör

A cél egy külső Synology NAS (DS212j, DSM 6.2, ext4). Csak `ssh-rsa` kulcsot fogad, nincs SFTP-alrendszere, és Btrfs-snapshotot sem tud, ezért NAS-oldali verziózás csak hardlinkes másolatokkal volna megoldható.

**Nyitott kérdés:** a tükör a szerverről írható, tehát egy kompromittált hoszt a mentést is törölhetné. A titkok (`/root`, `/etc/shadow`, `.env` fájlok, tanúsítványkulcsok) titkosítatlanul vannak a NAS-on.

# Visszaállítás új szerverre

A pontos parancsok az `infra/host-config` README „Mentés és visszaállítás” részében vannak. Röviden:

1. A teljes állomány visszamásolása rootként, `-M--fake-super` kapcsolóval, egy ideiglenes könyvtárba.
2. Csomagok telepítése a `/srv/backup/system/apt-manual.txt` alapján, majd az `/etc` válogatva a helyére, és a `/srv`, `/home`, `/root`, `/var/www`, `/var/spool/cron`, `/usr/local/sbin` vissza.
3. `sudo /srv/host-config/install.sh` a hoszt saját fájljaihoz.
4. A stackek indítása üres adatbázissal, majd a legfrissebb dumpok betöltése (`redmine_production`, `softwares`, `gitea`, `matomo`, `resourcespace`).
5. SQLite: a `*-backup.*` másolatok a helyükre, leállított stack mellett.
6. Docker-volume-ok: a ResourceSpace fájltár és a Matomo volume tartalma vissza.

# Fájlszerkezet

A mentőrepó (`infra/backup-scripts`):

```text
.
├── Makefile                # az 1. lánc minden feladata
└── database/
    ├── mariadb_backup.sh
    ├── mysql_backup.sh
    └── pg_backup.sh        # örökség, már nem fut
```

A 2. lánc az `infra/host-config` repóban van: `files/usr/local/sbin/vps-backup-sync`, `files/etc/systemd/system/vps-backup-sync.{service,timer}`, `files/etc/logrotate.d/vps-backup-sync`. Telepítés: `sudo ./install.sh`.

A szerveren (`BACKUP_BASE=/srv/backup`):

```text
/srv/backup/
├── database/                     # dumpok, 7 nap
│   ├── gitea-2026-10-16-02-00.sql
│   ├── redmine_production-2026-10-16-02-00.sql
│   ├── softwares-2026-10-16-02-00.sql
│   ├── matomo-2026-10-16-05-03.sql
│   └── resourcespace-2026-10-16-05-03.sql
├── repositories/                 # az összes Gitea-repó tükre
├── system/                       # csomaglista (dpkg, apt-mark)
└── archive-2026-10-15/           # a takarításkor törölt volume-ok tar.gz archívjai
```

# Ellenőrzés

- A tükör naplója a hoszton (`/var/log/vps-backup-sync.log`): minden lépés `OK` vagy `HIBA` sorral zárul.
- Hibátlan futás után a szkript Uptime Kuma pusht küld; ha 26 óráig nem jön jelzés, riasztás megy a Discord Alert csatornára.
- Grafana: a **VPS: Backup** dashboard mutatja az utolsó futás állapotát, a dumpok korát és méretét, a tükör méretét és a mentés naplósorait. A metrikákat a szkript a node-exporter textfile collectorának írja (`/srv/stacks/observability/textfile/vps_backup.prom`), a naplósorok a Lokiban vannak (`{service_name="cron-jobs", program="vps-backup-sync"}`). A Grafana: https://grafana.teletypegames.org (belépés Gitea-fiókkal).
- Ha egy adatbázis legfrissebb dumpja elavul, a Grafana **Database dump stale** riasztása szól Discordra.
- A dumpkönyvtárban minden adatbázisnak minden napra kell lennie friss fájljának; ha egy előtag eltűnik vagy megáll, a lánc elakadt.

# Repók

- https://git.teletypegames.org/infra/backup-scripts
- https://git.teletypegames.org/infra/host-config

'; var prevLevel = 2; for (var i = 0; i < headings.length; i++) { var h = headings\[i\]; var text = h.textContent.trim(); var slug = text.toLowerCase() .replace(/\[áàâä\]/g,'a').replace(/\[éèêë\]/g,'e').replace(/\[íìîï\]/g,'i') .replace(/\[óòôöő\]/g,'o').replace(/\[úùûüű\]/g,'u') .replace(/\[^a-z0-9\]+/g, '-').replace(/^-|-$/g, ''); if (!slug) slug = 'heading-' + i; if (used\[slug\]) { slug += '-' + i; } used\[slug\] = true; h.id = slug; var level = parseInt(h.tagName.charAt(1)); var cls = level > 2 ? ' class="toc-child"' : ''; html += '- [' + text + '](#'%20+%20slug%20+%20')
'; } html += '
'; toc.innerHTML = html; // Scroll-spy: highlight current heading var links = toc.querySelectorAll('a'); var ids = \[\]; for (var j = 0; j < links.length; j++) ids.push(links\[j\].getAttribute('href').slice(1)); function updateActive() { var current = ''; for (var k = 0; k < ids.length; k++) { var el = document.getElementById(ids\[k\]); if (el && el.getBoundingClientRect().top <= 80) current = ids\[k\]; } for (var m = 0; m < links.length; m++) { links\[m\].parentNode.classList.toggle('active', links\[m\].getAttribute('href') === '#' + current); } } window.addEventListener('scroll', updateActive, { passive: true }); updateActive(); })();

---

## Navigation

- Parent: [Infrastruktúra](https://wiki.teletypegames.org/hu/infrastructure.md)
- Next: [Üzembe helyezés](https://wiki.teletypegames.org/hu/infrastructure/deployment.md)
