--- title: t610 → TrueNAS автобэкап конфигов created: 2026-09-14 updated: 2026-09-14 type: tech namespace: family tags: [truenas, t610, backup, smb, ssh, cron, ha-os, done] related: - "[[family/plans/t610-home-automation]]" - "[[family/how-to/truenas-access]]" - "[[family/how-to/truenas-rclone-backup]]" - "[[family/how-to/gitea-config]]" --- # t610 → TrueNAS — автобэкап конфигов > **Задача (п.8 / A3 плана [[family/plans/t610-home-automation]]):** конфиги t610 (HA OS) регулярно складывать на TrueNAS, откуда они автоматически уезжают в Mail.ru Cloud через уже существующий rclone-бэкап TrueNAS. ## Схема (принята 2026-09-14) ``` t610 (/config, /addons, /addon_configs) │ tar ▼ TrueNAS pull (крон от юзера nas, ssh с ключом) │ ▼ /mnt/RED_2TB/backup/t610/ ← ZFS-датасет, владелец nas:nas, 770 │ SMB-шара "t610" (id=3) — для ручного доступа Alex с Mac/телефона │ ▼ rclone backup.sh (воскресенье 03:00, контейнер rclone) │ run_sync "backup" /data/backup "mailru-crypt:" ▼ Mail.ru Cloud (зашифровано) ``` **Ключевые решения и почему так:** 1. **Транспорт — PULL с TrueNAS, а не push с t610.** На t610 не надо ставить креды TrueNAS и держать лишние журналы; TrueNAS знает, где лежит архив. Крон TrueNAS работает под юзером **`nas`**, не под `truenas_admin` и не под root. 2. **Пользователь `nas` (uid 1000) — владелец датасета и ключа.** `truenas_admin` — админ (`zsh`, `builtin_administrators`) — держать его ключ на чужом хосте неправильно (Alex: «думаешь админом бэкап делать?»). `nas` — штатный NAS-юзер, `nas_users` gid=3000. 3. **Целевой датасет — `/mnt/RED_2TB/backup/t610`** (именно датасет, не папка). Причина: он **попадает внутрь `/mnt/RED_2TB/backup`**, который уже целиком уходит в rclone (`run_sync "backup" /data/backup "mailru-crypt:"`). **Ничего в `backup.sh` править не надо** — файлы уезжают в облако автоматически. (Альтернативы `storage/` или `docker/` требовали бы правки root-owned `backup.sh`.) 4. **SMB-шара `t610`** — не для доставки (HA OS не умеет SMB-пуш), а **для ручного доступа Alex** к бэкапам с Mac/телефона без ssh. 5. **Ключ ограничен** на стороне t610: `from="192.168.2.197"` + `no-port-forwarding,no-pty,no-X11-forwarding,no-agent-forwarding`. Т.е. даже при утечке — только стянуть архив, шелла нет. ## ✅ СТАТУС: РАБОТАЕТ (проверено живым прогоном 2026-09-14) ``` cron TrueNAS (юзер nas, 03:30 ежедневно) └─ /mnt/RED_2TB/backup/t610/backup-t610.sh └─ ssh t610-backup "tar czf - <14 путей>" → 605 КБ архив └─ /mnt/RED_2TB/backup/t610/t610-config-.tar.gz (ротация 14) └─ rclone (вс 03:00, контейнер) → mailru-crypt: (Mail.ru, шифровано) ``` ### Что сделано | # | Шаг | Статус | Детали | |---|-----|--------|--------| | 1 | Датасет `RED_2TB/backup/t610` | ✅ | UI → Storage → Datasets → Add Dataset; parent `/mnt/RED_2TB/backup`, Name `t610`, Type Filesystem | | 2 | Права датасета | ✅ | `chown nas:nas` + `chmod 770` (Alex, System → Shell) | | 3 | SMB-шара | ✅ | `id=3 name=t610 path=/mnt/RED_2TB/backup/t610 enabled=true ro=false` | | 4 | ssh-ключ для pull | ✅ | Создан на Mac: `~/tmp-t610/backup-key/t610_backup_ed25519` (+`.pub`), ed25519, без пароля, comment `t610-backup-pull`, fingerprint `SHA256:PKDB/sTjM8WFitIjSG+vT27x1TOY3F2Vi6y8YFwK5wo` | | 5 | Публичный ключ на t610 | ✅ | `/root/.ssh/authorized_keys` (+1 строка, было 1 — ключ Alex). Бэкап: `authorized_keys.bak-20260914-210532` | | 6 | Приватный ключ на TrueNAS | ✅ | **`/mnt/RED_2TB/backup/t610/.ssh/id_ed25519`** (+ `config` с алиасом `t610-backup`), `nas:nas 600`. ⚠️ Итоговое место — **внутри `backup/t610`**, НЕ в `~nas/.ssh` (см. питфолл №9) | | 7 | Скрипт бэкапа | ✅ | `/mnt/RED_2TB/backup/t610/backup-t610.sh` (v3, `nas:nas 755`) | | 8 | Крон-задача под `nas` | ✅ | `cronjob` **id=3**, user=`nas`, `30 3 * * *`, enabled=true | | 9 | Живой прогон + проверка архива | ✅ | 2 прогона: `OK ... (605504 bytes)`, `OK ... (605873 bytes)`, `.err` пустой | | 10 | Проверка состава архива | ✅ | **111 файлов**; ключевые на месте: `configuration.yaml`, `automations.yaml`, `go2rtc.yaml`, `secrets.yaml`, `.storage/http` (фикс `trusted_proxies`), `addons/modbus-bridge/data/config.template.tmpl` (реле slave 104), `nodered/flows.json` | | 11 | Выход в облако | ✅ | `run_sync "backup" /data/backup "mailru-crypt:"` в `backup.sh`; контейнер `rclone` — `Up 5 days`; правок не требовалось | **Путь для архивов на TrueNAS:** `/mnt/RED_2TB/backup/t610/t610-config-.tar.gz`, лог — `backup.log` рядом. ### Как проверять (без ожидания 03:30) ```bash # лог + список архивов ssh truenas_admin@mallexxx.duckdns.org 'cat /mnt/RED_2TB/backup/t610/backup.log; ls -la /mnt/RED_2TB/backup/t610/' # статус задачи ssh truenas_admin@mallexxx.duckdns.org 'midclt call cronjob.query "[[\"id\",\"=\",3]]" | jq -r ".[] | {id,user,enabled,command,schedule}"' ``` > ⚠️ **НЕ проверять через `midclt call cronjob.run`** — даёт ложный `exit 137`/`143`. См. питфолл №10. ### ⚠️ НЕ ЗАКРЫТО — что ещё стоит добавить в архив (обсуждалось 2026-09-14, вечер-15) Alex задал вопрос: «что НЕ входит в архив, но что мы задолбаемся восстанавливать?». Ответ (проверено на живом t610): | # | Что | Где лежит | Почему критично | |---|-----|-----------|-----------------| | 1 | 🔴 **Опции всех 11 аддонов** | `/data/options.json` внутри контейнера аддона + Supervisor API `/addons//options` | mbusd (привязка `by-path`, гнездо 4), modbus-bridge (`usb-0:3`, **пароль mosquitto `mqtt1z3$`**, ZONT host/slave), zigbee2mqtt (**`network_key`** + порт `/dev/ttyACM0`), Node-RED (**крипто-секрет `0ce08a59caa2077e607b5f34044af0b0c`**, пароль админки), Mosquitto (user/pass), Terminal&SSH (`authorized_keys`) | | 2 | 🔴 **Zigbee `network_key`** | в **опциях** аддона zigbee2mqtt (не в `/config/zigbee2mqtt/`) | `coordinator_backup.json` в архиве есть, но без `network_key` сеть **не поднять** — все устройства перепаривать | | 3 | 🔴 **Node-RED `flows_cred.json`** | `/addon_configs/a0d7b954_nodered/` (не читается обычным листингом; секрет `$` — в опциях) | без крипто-секрета креды не расшифруются → **все ноды HA подключать заново** | | 4 | 🟡 `home-assistant_v2.db` (9.2M) + `-wal` (4.1M) | `/config/` | история сенсоров, **статистика энергии**, климат. Бэкапить на живой системе рискованно (неконсистентность) — через SQLite backup API | | 5 | 🟡 Файлы `*.bak-*` | `/config/` (6 config + 4 automations) | точки отката миграции, размер мизерный | **Полный список аддонов t610 (проверено через Supervisor API):** `core_ssh`, `core_mosquitto`, `a0d7b954_nodered`, `core_samba` (stopped), `core_configurator`, `45df7312_zigbee2mqtt`, `local_mbusd`, `local_modbus-bridge`, `local_ustreamer` (stopped), `a889bffc_go2rtc` (stopped), `a889bffc_go2rtc-hardware`. **Не нужно бэкапить:** `/config/.cache`, `deps`, `tts`, `.cloud` (пустые/кеш), `.HA_VERSION`, `home-assistant_v2.db-shm`. **Решение (предложено, ожидает ответа Alex):** добавить в `backup-t610.sh` выгрузку опций аддонов через Supervisor API в JSON перед `tar`. Целевой размер архива ~10–15 МБ. ## Ключевые питфоллы (найдены в этой сессии) ### 1. 🔴 `from="192.168.2.197"` — Mac НЕ подходит для проверки ключа Mac заходит на t610 как **`192.168.2.157`** (через NAT Rasputin), а не как `.197`. Поэтому `ssh -i <ключ> root@192.168.2.176` **с Mac всегда даёт `Permission denied (publickey)`** — это **правильное поведение** ограничения, а не поломка ключа. Проверять pull-ключ **только с TrueNAS** (путь к конфигу — итоговый, см. питфолл №9): ```bash ssh -F /mnt/RED_2TB/backup/t610/.ssh/config t610-backup 'echo ok' ``` > ⚠️ Это тот же питфолл `.157` = NAT Rasputin, что уже задокументирован для логов HA. ### 2. 🔴 `Failed to load datasets: /mnt/.ix-apps/app_configs` — ломает ВЕСЬ UI датасетов **Симптом:** UI TrueNAS (Storage → Datasets, Apps, Datasets) — «Failed to load datasets», дерево датасетов не открывается, невозможно создать датасет/шару. **Причина:** после пересоздания пула (2026-08-21) каталог `app_configs` внутри датасета `ix-apps` не был создан. UI на старте **безусловно** читает `/mnt/.ix-apps/app_configs` и валит всё дерево. **Факты:** `RED_2TB/ix-apps` (8.29G) существует, смонтирован на `/mnt/.ix-apps`, `docker.config` → `pool=RED_2TB, dataset=RED_2TB/ix-apps` (пул Apps выбран корректно). Внутри был только `docker/` (`drwx--x--- root root`). Choose Pool → **не помогло**. **Фикс (под root, WebUI → System → Shell):** ```bash mkdir -p /mnt/.ix-apps/app_configs ``` > 📌 **Проверено:** фикс сработал, UI ожил. `mkdir` — shell-команда, не действие в UI. ### 3. 🔴 `aclmode: DISCARD aclmode may not be set for NFSv4 acl type` при создании датасета **Причина:** в форме создания датасета выставлен ACL Mode = `DISCARD`, что **запрещено** при `acltype=NFSv4` (весь пул RED_2TB на NFSv4). **Фикс:** **ACL Mode = `Passthrough`** (или пусто — подставится `passthrough`), ACL Type = `NFSv4`. Результат: `RED_2TB/backup/t610` → `aclmode=passthrough, acltype=nfsv4`. ### 4. 🔴 POSIX `setfacl` на NFSv4-датасете НЕ работает ``` setfacl -m user:truenas_admin:rwx /mnt/RED_2TB/backup/t610 → setfacl: Operation not supported ``` При `acltype=nfsv4` POSIX-setfacl не поддерживается. Менять владельца/права — только **`chown` под root** или **UI → Datasets → Edit → Permissions/ACL** (NFSv4-редактор). ### 5. Шары SMB на TrueNAS хранятся в registry, НЕ в `/etc/smb4.conf` `/etc/smb4.conf` содержит только `[global]` + `include = registry` + `registry shares = True`. Поэтому `grep имя_шары /etc/smb4.conf` и `testparm` **ничего не находят** — это не признак, что шара не создалась. Проверять через `midclt call sharing.smb.query`. > `testparm`/`smbclient -L` от `truenas_admin` дают `regdb_init: Permission denied` на `/var/run/samba-cache/registry.tdb` — проверка от непривилегированного юзера **неинформативна**. ### 6. `zfs`/`zpool` не в PATH у `truenas_admin` `zfs list` → пусто/`command not found`. Вызывать по абсолютному пути: **`/sbin/zfs`**, **`/sbin/zpool`**. (Иначе можно ошибочно решить, что датасетов нет.) ### 7. `truenas_admin` не может писать в `~nas` — итог: ключ держим в `backup/t610/.ssh` (см. №9) `~nas` = `/mnt/RED_2TB/storage/nas`. Промежуточная попытка класть ключ туда **провалилась** (см. №9) — итоговое место ключа: **`/mnt/RED_2TB/backup/t610/.ssh/`**. ### 8. Пароль `1316261` — ❌ НЕ от TrueNAS В доке `[[family/how-to/truenas-access]]` строка «Пароль root: `1316261`» **ошибочна** для TrueNAS. Alex: «Это не пароль от truenas». `1316261` — пароль от OpenWrt-роутера `192.168.2.2` (там он и правильный). **Для TrueNAS root-операций использовать WebUI → System → Shell** (работает под root, пароль не нужен). > 📌 Alex работает под root по SSH сам — **не предлагать ему WebUI-инструкции**, если он уже сказал, что у него есть root-shell. ### 9. 🔴 Ключ класть в `backup/t610/.ssh`, НЕ в `~nas/.ssh` — родительский `storage/` непроходим для `nas` **Симптом:** `Can't open user config file /mnt/RED_2TB/storage/nas/.ssh/config: Permission denied` — при том что сам `.ssh` был `nas:nas 700`. **Причина:** `nas` не может пройти **сквозь родителей**: ``` /mnt/RED_2TB/storage drwxr-x--- truenas_admin:truenas_admin ← nas не владелец, группы хватает только на r-x /mnt/RED_2TB/storage/nas drwxrwx--- truenas_admin:truenas_admin ← nas не владелец и не в группе → нет x /mnt/RED_2TB/storage/nas/.ssh drwx------ nas:nas ← сам в порядке, но путь закрыт ``` `truenas_admin` — **не владелец** `~nas` (после chown), а группа имеет только `r-x` → **создавать там файлы нельзя** (`mkdir: Permission denied`). **Решение (root НЕ нужен):** `/mnt/RED_2TB/backup/t610` — `nas:nas 770`, группа имеет `rwx`, `truenas_admin` в группе `nas` → пишет свободно. Ключ и `config` кладутся туда, затем `chown nas:nas` (работает **без root**, т.к. `truenas_admin` — владелец созданных файлов): ```bash mkdir -p /mnt/RED_2TB/backup/t610/.ssh cp /tmp/bk_key /mnt/RED_2TB/backup/t610/.ssh/id_ed25519 # ... config ... chown nas:nas /mnt/RED_2TB/backup/t610/.ssh/{config,id_ed25519} # ← БЕЗ root, работает ``` > 💡 **Урок:** `chown nas:nas` на **свои** файлы проходит без root. Root нужен только для чужих. Прежде чем просить Alex'а — проверить `ls -ld` по всей цепочке родителей и `touch` на запись. ### 10. 🔴 `midclt call cronjob.run` даёт ЛОЖНЫЙ `exit 137`/`exit 143` — не признак поломки скрипта **Симптом:** задача падает за ~1 сек с `CronTask "..." exited with 137 (non-zero) exit status` — хотя скрипт рабочий. **Причина:** middleware прибивает таск (SIGKILL=137 / SIGTERM=143), когда родительский job `cronjob.run` завершается раньше дочернего процесса. Это баг API-пути, а не скрипта. **Как отличить:** смотреть **несколько** job'ов и **файловый лог скрипта**. Реальные ошибки скрипта видны как его собственные коды (`exit 2`, `exit 3`) + запись в `backup.log`/`.err`. **Правильная проверка:** ставить задачу на `* * * * *`, **ждать реального срабатывания** и смотреть появившийся архив, потом вернуть расписание: ```bash midclt call cronjob.update 3 '{"schedule":{"minute":"30","hour":"3","dom":"*","month":"*","dow":"*"}}' ``` > ⚠️ Не «проверять» циклом `sleep` вслепую — узнавать по факту появления файла/записи в логе. ### 11. 🔴 Список путей для `tar` через ssh: не передавать многострочной переменной **Симптом:** `tar: empty archive` + `bash: line N: config/configuration.yaml: Permission denied` (пути выполняются как команды). **Причина:** многострочная `$FILES`, подставленная в ssh-команду, интерпретируется **на удалённой стороне** как отдельные команды. **Фикс:** список путей — **одной строкой прямо в ssh-команде**: ```sh ssh -F "$SSHCFG" "$SSHHOST" 'tar czf - -C / config/configuration.yaml config/automations.yaml ...' > "$OUT" ``` ### 12. `scp` поверх чужого файла не работает, но `mv` в групповом `rwx`-каталоге — работает `scp` даёт `Permission denied` при перезаписи файла, принадлежащего `nas`. Обход: положить под новым именем и сделать `mv` (каталог `770` даёт группе `rwx`). ⚠️ После `mv` владелец/права **сбрасываются** на копирующего → обязателен `chmod 755` + `chown nas:nas`. ### 13. `cronjob.run` вызывается кроном как `midclt call cronjob.run true` — задачи от `nas` работают Проверено: `/etc/cron.d/middlewared` содержит `* * * * * root ... midclt call cronjob.run 2 true`. Системный `cron -f` + `busybox crond -f` живут. Задачи от `nas` **выполняются штатно** (job state=SUCCESS, файлы появляются) — «крон не работает» было ложной тревогой от проверки файла до первой минуты. ### 14. `set -u` + `exit` в циклах на zsh-стороне ломает проверки Проверки через `ssh ... 'ls /path/*.tar.gz'` на **zsh**-цели дают `zsh:1: no matches found` и рвут цикл (скрипт выходит до `sleep`). Использовать `bash -c` на удалённой стороне или `test -f` / `ls -1 ... 2>/dev/null`. ## Команды (итоговые, воспроизведение) ```bash # ─── 1. Создание ключа (Mac) ─── ssh-keygen -t ed25519 -N '' -C 't610-backup-pull' -f ~/tmp-t610/backup-key/t610_backup_ed25519 # fingerprint: SHA256:PKDB/sTjM8WFitIjSG+vT27x1TOY3F2Vi6y8YFwK5wo # ─── 2. Публичный ключ на t610 (с ограничениями по IP и без шелла) ─── KEYBODY=$(awk '{print $2}' ~/tmp-t610/backup-key/t610_backup_ed25519.pub) ENTRY="from=\"192.168.2.197\",no-port-forwarding,no-pty,no-X11-forwarding,no-agent-forwarding ssh-ed25519 ${KEYBODY} t610-backup-pull" ssh root@192.168.2.176 'cp -a /root/.ssh/authorized_keys /root/.ssh/authorized_keys.bak-$(date +%Y%m%d-%H%M%S)' printf '%s\n' "$ENTRY" | ssh root@192.168.2.176 'cat >> /root/.ssh/authorized_keys && chmod 600 /root/.ssh/authorized_keys' # ─── 3. Приватный ключ на TrueNAS в backup/t610/.ssh (НЕ в ~nas/.ssh — см. питфолл 9) ─── scp ~/tmp-t610/backup-key/t610_backup_ed25519 truenas_admin@mallexxx.duckdns.org:/tmp/bk_key ssh truenas_admin@mallexxx.duckdns.org ' mkdir -p /mnt/RED_2TB/backup/t610/.ssh cp /tmp/bk_key /mnt/RED_2TB/backup/t610/.ssh/id_ed25519 chmod 600 /mnt/RED_2TB/backup/t610/.ssh/id_ed25519 cat > /mnt/RED_2TB/backup/t610/.ssh/config </dev/null || usermod -a -G nas truenas_admin # truenas_admin в группу nas # ─── 5. SMB-шара (от truenas_admin, midclt) ─── midclt call sharing.smb.query > /mnt/RED_2TB/storage/shares-before-$(date +%Y%m%d-%H%M%S).json # ДАМП ПЕРЕД midclt call sharing.smb.create '{"purpose":"DEFAULT_SHARE","path":"/mnt/RED_2TB/backup/t610", "name":"t610","comment":"Backup t610 (HA OS) configs","ro":false,"browsable":true, "guestok":false,"timemachine":false,"enabled":true}' # ─── 6. Скрипт бэкапа (v3) + права ─── scp ~/tmp-t610/backup-t610-v3.sh truenas_admin@mallexxx.duckdns.org:/mnt/RED_2TB/backup/t610/backup-t610.sh ssh truenas_admin@mallexxx.duckdns.org ' chmod 755 /mnt/RED_2TB/backup/t610/backup-t610.sh chown nas:nas /mnt/RED_2TB/backup/t610/backup-t610.sh' # ─── 7. Крон-задача (id=3, юзер nas, 03:30 ежедневно) ─── midclt call cronjob.create '{"user":"nas","command":"/mnt/RED_2TB/backup/t610/backup-t610.sh", "description":"Backup t610 HA configs","enabled":true, "schedule":{"minute":"30","hour":"3","dom":"*","month":"*","dow":"*"}, "stdout":false,"stderr":false}' # ─── 8. Проверка pull-ключа — ТОЛЬКО С TrueNAS ─── ssh -F /mnt/RED_2TB/backup/t610/.ssh/config t610-backup 'echo ok' ``` ## Состав бэкапа t610 (✅ фактический — 111 файлов, ~605 КБ) Из `/config`: `configuration.yaml`, `automations.yaml`, `scripts.yaml`, `scenes.yaml`, `secrets.yaml`, `.storage/` (**без** `home-assistant_v2.db*`), `go2rtc.yaml`, `zigbee2mqtt/`, `www/`. Плюс `/addons/{mbusd,modbus-bridge,ustreamer}` (код + `data/config.template.tmpl` — правка реле slave 104), `/addon_configs/{45df7312_zigbee2mqtt,a0d7b954_nodered}` (flows/settings). **Ротация:** `KEEP=14` архивов (`t610-config-.tar.gz`). > ⚠️ НЕ входит (и стоит добавить): **опции аддонов**, `network_key` Zigbee, `flows_cred.json`, `home-assistant_v2.db`. Детали — раздел «НЕ ЗАКРЫТО» выше. ### Скрипт (суть) ```sh DEST=/mnt/RED_2TB/backup/t610 ; SSHCFG=$DEST/.ssh/config ; SSHHOST=t610-backup ; KEEP=14 # tar собирается НА t610, пути — ОДНОЙ СТРОКОЙ (питфолл 11) ssh -F "$SSHCFG" -o BatchMode=yes -o ConnectTimeout=15 "$SSHHOST" \ 'tar czf - -C / config/configuration.yaml config/automations.yaml ... ' > "$OUT" 2> "$DEST/.err" # проверка размера <1024 → .BAD + exit 2 ; ssh-ошибка → exit 3 ; ротация до KEEP ``` Скрипт на Mac (рабочие копии): `~/tmp-t610/backup-t610-v3.sh`, `~/tmp-t610/backup-t610.sh`. Бэкап-ключ на Mac: `~/tmp-t610/backup-key/t610_backup_ed25519`. Скрипты: `mk_backup_key.sh`, `add_backup_key_t610.sh`, `push_backup_key_truenas.sh`, `move_key_to_backup.sh`, `cleanup_backup.sh`, `phase1_diag.sh`, `phase2_key.sh`, `wait_archive.sh`. ## Связанный синк в git (сделан в этой же сессии) Репозиторий **`~/Automation/HA-ZONT-Modbus`** → Gitea (`git_admin/HA-ZONT-Modbus`, private). Коммит **`9d31118`** «Sync from t610 prod: automations device_ids, go2rtc camera, bridge relay» — запушен, remote SHA = local SHA. | Файл | Что синкнуто | |---|---| | `homeassistant/configuration.yaml` | http-блок убран (перенесён в `.storage/http`); **`modbus.host` `192.168.2.197` → `192.168.2.176`** | | `homeassistant/automations.yaml` | перегенерированы `device_id` (миграция на t610), `light.0xa4c13882a4b42db0` → `light.bed_dimmer`, +триггер `illuminance`, +условие `is_occupied` (ночной свет душевой) | | `homeassistant/go2rtc.yaml` | **НОВЫЙ** — камера go2rtc-hardware, ffmpeg H.264 + `rotate=90` | | `config.yml` | +«Boiler controller power (Zigbee relay)» slave 104 / рег 1 | | `modbus_ha_bridge.py` | уже совпадал (sha идентичен) | | `scripts.yaml` | уже совпадал (sha идентичен) | > 📌 Паттерн: **сначала сравнить прод↔репо по sha256, потом тащить только изменившееся.** Креды Gitea — `~/.git-credentials` (chmod 600) + `credential.helper=store`, remote — **чистый URL без токена**.