pcb-ai-engineer/refs: add self-hosted mirror section (Altium Celestial)
The original setup guide covered connecting Altium directly to the
portal SQL server. That works but has three drawbacks under RU
conditions: ~60-second Altium startup over VPN, daily VPN dependency,
single point of failure at Mark Harris's hosting.
New section 11 documents the self-hosted alternative we just built and
verified end-to-end:
- Two independent mirrors:
- homework/altium-library: Gitea pull-mirror of issus/altium-library
with LFS (SchLib + PcbLib + STEP, ~6 GB)
- homework/celestial-mirror-db: MSSQL 2022 Express in Docker on
192.168.9.147, populated weekly by a pymssql-based sync job with
best-effort + row-count/schema fingerprint skip logic
- Results: Altium startup <1s (100x faster), VPN only needed once a
week for the sync runner, full control over the dataset
- Full deployment sequence (Gitea migrate API → docker compose up →
first manual full-sync → client DbLib rewrite)
- ConnectionString rewrite details (altium_reader user, LAN IP,
Encrypt=Optional/TrustServerCertificate=Yes for self-signed cert)
- MPN-to-view lookup strategies (Shift+C in Altium; dynamic SQL that
scans all 168 tables)
- Troubleshooting specific to the mirror stack
This commit is contained in:
@@ -545,8 +545,219 @@ Write-Host "`nГотово. Открывай Altium → Components panel → Fil
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 10. Changelog этой инструкции
|
## 11. Self-hosted mirror (опционально, ускорение startup ×100)
|
||||||
|
|
||||||
|
Разделы 1–9 подключают Altium напрямую к портальному SQL-серверу Mark
|
||||||
|
Harris'а. Это работает, но:
|
||||||
|
|
||||||
|
- Каждый запуск Altium — 30–90 секунд на ~600 метадата-запросов через
|
||||||
|
WAN (OVH France). VPN добавляет ещё RTT.
|
||||||
|
- Требуется VPN при каждой работе с библиотекой (если RKN режет 1433 к
|
||||||
|
OVH, а он обычно режет).
|
||||||
|
- Зависимость от доступности `db.altiumlibrary.com` — если Mark
|
||||||
|
выключит сервер, всё встанет.
|
||||||
|
- Нельзя добавлять свои компоненты в общую БД — только в отдельный
|
||||||
|
custom DbLib.
|
||||||
|
|
||||||
|
Альтернатива — **self-hosted mirror**: зеркалим и git-репо (SchLib/PcbLib/STEP
|
||||||
|
через LFS), и SQL-БД (параметры компонентов). Клиенты ходят только в LAN,
|
||||||
|
VPN нужен раз в неделю для sync-job'а.
|
||||||
|
|
||||||
|
### Результат
|
||||||
|
|
||||||
|
- Startup Altium: **<1 сек** (проверено на Altium 26.4.1, январь 2026)
|
||||||
|
- Нет зависимости от WAN и от upstream'а в ежедневной работе
|
||||||
|
- Полный контроль — можно доливать свои views/компоненты
|
||||||
|
- Обновления — раз в неделю автоматически по cron
|
||||||
|
|
||||||
|
### Архитектура
|
||||||
|
|
||||||
|
```
|
||||||
|
┌──────────────────────────┐ pull mirror (Gitea, 24h) ┌─────────────────────────┐
|
||||||
|
│ github.com/issus/ │◀─────── HTTPS + LFS ─────────│ homework/altium-library │
|
||||||
|
│ altium-library │ │ (Gitea mirror, ~6 GB) │
|
||||||
|
└──────────────────────────┘ └──────────┬──────────────┘
|
||||||
|
│ git clone
|
||||||
|
▼
|
||||||
|
┌─────────────────────────┐
|
||||||
|
│ Altium (client) │
|
||||||
|
│ SchLib/PcbLib/STEP │
|
||||||
|
│ from local clone │
|
||||||
|
└──────────┬──────────────┘
|
||||||
|
│ SQL queries
|
||||||
|
▼
|
||||||
|
┌──────────────────────────┐ weekly sync (Gitea Actions) ┌─────────────────────────┐
|
||||||
|
│ db.altiumlibrary.com │◀───── pymssql, VPN ──────────│ homework/ │
|
||||||
|
│ :1433 (upstream SQL) │ │ celestial-mirror-db │
|
||||||
|
└──────────────────────────┘ │ + MSSQL 2022 Express │
|
||||||
|
│ on 192.168.9.147:1433 │
|
||||||
|
└─────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### Два независимых компонента
|
||||||
|
|
||||||
|
**Git-mirror** (`homework/altium-library`):
|
||||||
|
- Gitea pull-mirror, интервал 24h, LFS включён
|
||||||
|
- Содержит SchLib, PcbLib, STEP, sample projects — всё из upstream
|
||||||
|
- Клиенты клонируют с `ssh://git@192.168.7.179:2222/homework/altium-library.git`
|
||||||
|
или HTTPS по LAN
|
||||||
|
|
||||||
|
**SQL-mirror** (`homework/celestial-mirror-db`):
|
||||||
|
- Docker-стек: MSSQL 2022 Express на 192.168.9.147:1433 (LAN only)
|
||||||
|
- Sync-скрипт `sync/celestial_sync.py`: best-effort, atomic swap через
|
||||||
|
staging+`sp_rename`, row-count+schema fingerprint skip-логика
|
||||||
|
- Gitea Actions workflow: `workflow_dispatch` + weekly cron понедельник
|
||||||
|
03:00 UTC
|
||||||
|
- Два SQL-user'а: `sync_writer` (DDL+DML для CI) и `altium_reader`
|
||||||
|
(SELECT для Altium)
|
||||||
|
|
||||||
|
### Как развернуть с нуля
|
||||||
|
|
||||||
|
Последовательность в новой инсталляции (полный setup ~2 часа на первый
|
||||||
|
раз, включая начальный sync ~40 мин):
|
||||||
|
|
||||||
|
**1. Gitea pull-mirror git-репо**
|
||||||
|
|
||||||
|
В Gitea UI: `+ → New Migration → GitHub` (или через API):
|
||||||
|
```
|
||||||
|
Clone URL: https://github.com/issus/altium-library.git
|
||||||
|
Owner: homework
|
||||||
|
Name: altium-library
|
||||||
|
Type: Mirror (pull)
|
||||||
|
Interval: 24h
|
||||||
|
LFS: ✓ enabled
|
||||||
|
```
|
||||||
|
|
||||||
|
Либо через API:
|
||||||
|
```bash
|
||||||
|
curl -X POST -H "Authorization: token $GITEA_TOKEN" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
"$GITEA_URL/api/v1/repos/migrate" -d '{
|
||||||
|
"clone_addr": "https://github.com/issus/altium-library.git",
|
||||||
|
"repo_owner": "homework",
|
||||||
|
"repo_name": "altium-library",
|
||||||
|
"service": "git",
|
||||||
|
"mirror": true,
|
||||||
|
"mirror_interval": "24h0m0s",
|
||||||
|
"lfs": true
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
|
Первичная миграция тянет 5–6 ГБ с GitHub, занимает 30–90 минут.
|
||||||
|
|
||||||
|
**2. Docker-стек celestial-mirror-db**
|
||||||
|
|
||||||
|
Клонировать `homework/celestial-mirror-db`, заполнить `.env` сильными
|
||||||
|
паролями (см. `.env.example`), `docker compose up -d`. Init-контейнер
|
||||||
|
создаст БД, логины, роли. Compose-файл биндит порт на 192.168.9.147:1433
|
||||||
|
(только LAN, не 0.0.0.0). Подробная инструкция — в README репо.
|
||||||
|
|
||||||
|
**3. Первый sync**
|
||||||
|
|
||||||
|
В Gitea UI: `Actions → Sync Celestial DB → Run workflow`, mode=full-sync.
|
||||||
|
Занимает 30–60 минут через VPN. На VPN должен быть маршрут до
|
||||||
|
`51.68.218.24` (OVH France) — на MikroTik это address-list с policy-based
|
||||||
|
routing через xray/AmneziaWG.
|
||||||
|
|
||||||
|
**4. Подключение клиента (Altium)**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Клиентская машина
|
||||||
|
cd C:\Work
|
||||||
|
git clone ssh://git@192.168.7.179:2222/homework/altium-library.git
|
||||||
|
cd altium-library
|
||||||
|
git lfs pull
|
||||||
|
```
|
||||||
|
|
||||||
|
Копируем портальный DbLib рядом как `-local.DbLib`, правим `ConnectionString`:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
# Было:
|
||||||
|
ConnectionString = Provider=SQLNCLI11.1; User ID=alib_xxx; Password=xxx; \
|
||||||
|
Initial Catalog=altium_library; Data Source=db.altiumlibrary.com,1433; \
|
||||||
|
Initial File Name=""; Server SPN=""
|
||||||
|
|
||||||
|
# Стало:
|
||||||
|
ConnectionString = Provider=SQLNCLI11.1; User ID=altium_reader; Password=<из .env>; \
|
||||||
|
Initial Catalog=altium_library; Data Source=192.168.9.147,1433; \
|
||||||
|
Encrypt=Optional; TrustServerCertificate=Yes; \
|
||||||
|
Initial File Name=""; Server SPN=""
|
||||||
|
```
|
||||||
|
|
||||||
|
Изменилось: `User ID`, `Password`, `Data Source`, и добавлены
|
||||||
|
`Encrypt=Optional; TrustServerCertificate=Yes` — потому что MSSQL в Docker
|
||||||
|
с self-signed сертификатом.
|
||||||
|
|
||||||
|
В Altium: `Components panel → File-based Libraries Preferences → Installed
|
||||||
|
→ Uninstall старого (портального) → Install нового (local)`. Startup
|
||||||
|
<1 секунды.
|
||||||
|
|
||||||
|
### Поиск компонента по MPN без знания категории
|
||||||
|
|
||||||
|
В DBLib-архитектуре Altium показывает компоненты в рамках одной view
|
||||||
|
(категории). Если MPN известен, а категория нет:
|
||||||
|
|
||||||
|
**Способ 1 — через Altium:** Hotkey `Shift+C` (File-based Libraries Search)
|
||||||
|
→ Search for: `*STSPIN32G4*`, Scope: `Libraries on path`, Search in:
|
||||||
|
`Components`. Выдаст список попаданий с колонкой "Library Ref".
|
||||||
|
|
||||||
|
**Способ 2 — SQL прямо в mirror:** Единичный запрос с dynamic SQL
|
||||||
|
просматривает все tables и находит категорию:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SET NOCOUNT ON;
|
||||||
|
DECLARE @needle NVARCHAR(100) = N'%STSPIN32G4%';
|
||||||
|
DECLARE @sql NVARCHAR(MAX) = N'';
|
||||||
|
|
||||||
|
SELECT @sql = @sql +
|
||||||
|
'IF EXISTS (SELECT 1 FROM [' + TABLE_NAME + '] WHERE [Part Number] LIKE @n) ' +
|
||||||
|
'SELECT ''' + TABLE_NAME + ''' AS [View], [Part Number], [Manufacturer], [Description] ' +
|
||||||
|
'FROM [' + TABLE_NAME + '] WHERE [Part Number] LIKE @n; '
|
||||||
|
FROM INFORMATION_SCHEMA.TABLES
|
||||||
|
WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME NOT LIKE '%__staging'
|
||||||
|
AND TABLE_NAME <> 'sync_status';
|
||||||
|
|
||||||
|
EXEC sp_executesql @sql, N'@n NVARCHAR(100)', @n=@needle;
|
||||||
|
```
|
||||||
|
|
||||||
|
Можно обернуть в shell-функцию `cfind`.
|
||||||
|
|
||||||
|
### Troubleshooting self-hosted mirror
|
||||||
|
|
||||||
|
**Sync job висит на первой view ~10 минут и фейлится с "DBPROCESS is dead":**
|
||||||
|
RKN режет TCP к `51.68.218.24:1433`. Проверяй что на VPN routing для этого
|
||||||
|
IP действительно активен с 192.168.9.147.
|
||||||
|
|
||||||
|
**`String or binary data would be truncated`:** Upstream view объявляет
|
||||||
|
NVARCHAR(N) в INFORMATION_SCHEMA, но возвращает строки длиннее. Фикс в
|
||||||
|
sync-скрипте — все строковые колонки мапятся в NVARCHAR(MAX). Если
|
||||||
|
видишь такую ошибку — `celestial_sync.py` ещё не имеет фикса, обнови
|
||||||
|
до коммита `b868b68` или новее.
|
||||||
|
|
||||||
|
**Weekly sync не стартует:** Gitea Actions требует чтобы в репо был
|
||||||
|
активный runner и на репо были включены Actions. Проверь
|
||||||
|
`Settings → Actions → General → Enabled`.
|
||||||
|
|
||||||
|
**Altium Components panel пустая:** SSH'нись в MSSQL и проверь:
|
||||||
|
```sql
|
||||||
|
SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES
|
||||||
|
WHERE TABLE_TYPE='BASE TABLE' AND TABLE_NAME NOT LIKE '%__staging';
|
||||||
|
-- Должно быть ~168.
|
||||||
|
|
||||||
|
SELECT TOP 1 * FROM dbo.sync_status ORDER BY id DESC;
|
||||||
|
-- status = 'ok', views_synced около 168, rows_synced ~250k.
|
||||||
|
```
|
||||||
|
|
||||||
|
### Ссылки на репозитории
|
||||||
|
|
||||||
|
- `homework/altium-library` — git mirror: <https://git.h3fq32.golive.ru/homework/altium-library>
|
||||||
|
- `homework/celestial-mirror-db` — Docker + sync: <https://git.h3fq32.golive.ru/homework/celestial-mirror-db>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 12. Changelog этой инструкции
|
||||||
|
|
||||||
| Дата | Изменения |
|
| Дата | Изменения |
|
||||||
|---|---|
|
|---|---|
|
||||||
| 2026-04-18 | Первая версия. Проверено на Altium Designer 26.4.1, Windows 11, MSOLEDBSQL 19.4.1.0, SQLNCLI 11.4.x. |
|
| 2026-04-18 | Первая версия. Проверено на Altium Designer 26.4.1, Windows 11, MSOLEDBSQL 19.4.1.0, SQLNCLI 11.4.x. |
|
||||||
|
| 2026-04-18 | Добавлен раздел 11 — self-hosted mirror с git + SQL зеркалами. Проверено end-to-end: startup <1 сек, 256 677 строк в локальной БД, weekly sync active. |
|
||||||
|
|||||||
Reference in New Issue
Block a user