sync: latest changes before Gitea migration

This commit is contained in:
Агальцов Антон committed 2026-04-26 17:09:31 +03:00
1 parent c2cc439fc5
commit acba5dd5f1
148 files changed
+13001 -696

No files matched your search

+187 -258
View File
@@ -38,6 +38,10 @@
<a class="nav-link" href="../plans/">Планы</a>
</li>
<li class="nav-item">
<a class="nav-link" href="../leadera/">Leadera</a>
</li>
<li class="nav-item">
<a class="nav-link" href="../guides/">Инструкции</a>
</li>
@@ -110,16 +114,6 @@
@@ -166,14 +160,6 @@
<h6 class="mt-3">Теги</h6>
<ul class="nav flex-column">
<li class="nav-item"><a class="nav-link" href="../tags/audit/">audit</a></li>
<li class="nav-item"><a class="nav-link" href="../tags/leadera/">leadera</a></li>
<li class="nav-item"><a class="nav-link" href="../tags/security/">security</a></li>
<li class="nav-item"><a class="nav-link" href="../tags/architecture/">architecture</a></li>
<li class="nav-item"><a class="nav-link" href="../tags/ssh/">ssh</a></li>
<li class="nav-item"><a class="nav-link" href="../tags/tunnel/">tunnel</a></li>
@@ -215,225 +201,82 @@
<div class="col-md-6 mb-4">
<div class="card h-100">
<div class="card-body">
<h3 class="card-title"><a href="../guides/leadera-audit/">Аудит Leadera — полный отчёт</a></h3>
<p class="card-text"><h1 id="аудит-проекта-leadera">Аудит проекта Leadera</h1>
<p><strong>Дата:</strong> 30.03.2026<br>
<strong>Версия:</strong> pre-production, миграции 1–5</p>
<hr>
<h2 id="1-обзор-проекта">1. Обзор проекта</h2>
<p>Leadera — SaaS-система управления IT-ландшафтом с диаграммами Ганта.</p>
<h3 id="стек">Стек</h3>
<h3 class="card-title"><a href="../guides/sand-a2v-space/">Подключение sand.a2v.space (Leadera Project)</a></h3>
<p class="card-text"><h2 id="архитектура">Архитектура</h2>
<pre tabindex="0"><code>Mac Studio
├─ Frontend (Angular) :4200 (pm2: leadera-fe)
├─ Backend (Go) :8080 (pm2: leadera-api)
└─ PostgreSQL 16 в Docker (Colima, container: app-leadera-db)
→ autossh SSH-туннель (-R 8082:localhost:4200 -R 8083:localhost:8080)
→ VPS 95.163.232.9
→ nginx HTTPS
→ https://sand.a2v.space
</code></pre><h2 id="параметры">Параметры</h2>
<table>
<thead>
<tr>
<th>Компонент</th>
<th>Технологии</th>
<th>Локальный порт</th>
<th>Туннель порт</th>
<th>pm2 имя</th>
</tr>
</thead>
<tbody>
<tr>
<td>Backend</td>
<td>Go 1.21+, Gin, PostgreSQL 16, pgx/v5 + sqlx, JWT (HMAC-SHA256)</td>
<td>Frontend (Angular)</td>
<td>4200</td>
<td>8082</td>
<td>leadera-fe</td>
</tr>
<tr>
<td>Frontend</td>
<td>Angular 21.1, Bootstrap 5, NgBootstrap, RxJS, Signals</td>
</tr>
<tr>
<td>Инфраструктура</td>
<td>Docker (Colima), pm2, nginx reverse proxy, VPS reg.ru</td>
<td>Backend (Go)</td>
<td>8080</td>
<td>8083</td>
<td>leadera-api</td>
</tr>
</tbody>
</table>
<h3 id="доменная-модель">Доменная модель</h3>
<pre tabindex="0"><code>User ──┬── Space (через space_members с role)
│
└── GanttChart (принадлежит Space)
├── GanttSection
└── GanttTask
</code></pre><p><strong>Роли:</strong> admin, editor, viewer — назначаются <strong>на уровне Space</strong> через таблицу <code>space_members</code>.</p></p>
<div class="tags">
<a href="../tags/audit/" class="tag">audit</a>
<a href="../tags/leadera/" class="tag">leadera</a>
<a href="../tags/security/" class="tag">security</a>
<a href="../tags/architecture/" class="tag">architecture</a>
</div>
</div>
</div>
</div>
<div class="col-md-6 mb-4">
<div class="card h-100">
<div class="card-body">
<h3 class="card-title"><a href="../guides/ssh-tunnels-vps/">SSH туннели для VPS reverse proxy</a></h3>
<p class="card-text"><h2 id="настройка-ssh-туннелей">Настройка SSH туннелей</h2>
<h3 id="vps-regru-951632329">VPS reg.ru (95.163.232.9)</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e"># На Mac Studio: создать туннель для каждого сервиса</span>
</span></span><span style="display:flex;"><span>ssh -N -R 8080:localhost:8080 root@95.163.232.9 <span style="color:#75715e"># leadera-api</span>
</span></span><span style="display:flex;"><span>ssh -N -R 8081:localhost:4096 root@95.163.232.9 <span style="color:#75715e"># opencode</span>
</span></span><span style="display:flex;"><span>ssh -N -R 8082:localhost:4200 root@95.163.232.9 <span style="color:#75715e"># leadera-fe</span>
</span></span><span style="display:flex;"><span>ssh -N -R 8083:localhost:8080 root@95.163.232.9 <span style="color:#75715e"># docs-a2v</span>
</span></span></code></pre></div><h3 id="настройка-launchd-plist">Настройка launchd plist</h3>
<p><strong>Файл</strong>: <code>~/Library/LaunchAgents/com.openclaw.sshtunnel.plist</code></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#75715e">&lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34;?&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">&lt;!DOCTYPE plist PUBLIC &#34;-//Apple//DTD PLIST 1.0//EN&#34; &#34;http://www.apple.com/DTDs/PropertyList-1.0.dtd&#34;&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;plist</span> <span style="color:#a6e22e">version=</span><span style="color:#e6db74">&#34;1.0&#34;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;dict&gt;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">&lt;key&gt;</span>Label<span style="color:#f92672">&lt;/key&gt;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">&lt;string&gt;</span>com.openclaw.sshtunnel<span style="color:#f92672">&lt;/string&gt;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">&lt;key&gt;</span>ProgramArguments<span style="color:#f92672">&lt;/key&gt;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">&lt;array&gt;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">&lt;string&gt;</span>ssh<span style="color:#f92672">&lt;/string&gt;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">&lt;string&gt;</span>-N<span style="color:#f92672">&lt;/string&gt;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">&lt;string&gt;</span>-R<span style="color:#f92672">&lt;/string&gt;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">&lt;string&gt;</span>8080:localhost:8080<span style="color:#f92672">&lt;/string&gt;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">&lt;string&gt;</span>root@95.163.232.9<span style="color:#f92672">&lt;/string&gt;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">&lt;/array&gt;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">&lt;key&gt;</span>RunAtLoad<span style="color:#f92672">&lt;/key&gt;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">&lt;true/&gt;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">&lt;key&gt;</span>KeepAlive<span style="color:#f92672">&lt;/key&gt;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">&lt;true/&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/dict&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/plist&gt;</span>
</span></span></code></pre></div><h3 id="автозапуск">Автозапуск</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e"># Загрузить plist</span>
</span></span><span style="display:flex;"><span>launchctl load ~/Library/LaunchAgents/com.openclaw.sshtunnel.plist
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Проверить статус</span>
</span></span><span style="display:flex;"><span>launchctl list | grep sshtunnel
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Удалить (при необходимости)</span>
</span></span><span style="display:flex;"><span>launchctl unload ~/Library/LaunchAgents/com.openclaw.sshtunnel.plist
</span></span></code></pre></div><h2 id="доступ-к-сервисам">Доступ к сервисам</h2>
<p>Через reverse proxy на VPS:</p></p>
<div class="tags">
<a href="../tags/ssh/" class="tag">ssh</a>
<a href="../tags/tunnel/" class="tag">tunnel</a>
<a href="../tags/vps/" class="tag">vps</a>
<a href="../tags/reverse-proxy/" class="tag">reverse-proxy</a>
</div>
</div>
</div>
</div>
<div class="col-md-6 mb-4">
<div class="card h-100">
<div class="card-body">
<h3 class="card-title"><a href="../guides/vps-reverse-proxy/">Настройка VPS как реверс-прокси</a></h3>
<p class="card-text"><h2 id="общая-схема">Общая схема</h2>
<pre tabindex="0"><code>Mac Studio (локальная сеть)
→ autossh (SSH-туннели)
→ VPS 95.163.232.9 (Debian)
→ nginx (HTTPS reverse proxy)
→ интернет
</code></pre><h2 id="что-нужно-на-vps">Что нужно на VPS</h2>
<h3 id="1-установленные-пакеты">1. Установленные пакеты</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>apt update
</span></span><span style="display:flex;"><span>apt install nginx certbot python3-certbot-nginx
</span></span></code></pre></div><h3 id="2-ssh-доступ">2. SSH-доступ</h3>
<ul>
<li>Авторизация только по ключам</li>
<li>Публичный ключ с Mac Studio добавлен в <code>/root/.ssh/authorized_keys</code></li>
</ul>
<h3 id="3-nginx">3. nginx</h3>
<p>Для каждого домена создать server block:</p>
<ul>
<li>HTTP → редирект на HTTPS</li>
<li>HTTPS с SSL-сертификатом Let&rsquo;s Encrypt</li>
<li><code>proxy_pass</code> на localhost-порт туннеля</li>
</ul>
<p>Пример структуры:</p></p>
<div class="tags">
<a href="../tags/vps/" class="tag">vps</a>
<a href="../tags/nginx/" class="tag">nginx</a>
<a href="../tags/ssh/" class="tag">ssh</a>
<a href="../tags/reverse-proxy/" class="tag">reverse-proxy</a>
<a href="../tags/devops/" class="tag">devops</a>
</div>
</div>
</div>
</div>
<div class="col-md-6 mb-4">
<div class="card h-100">
<div class="card-body">
<h3 class="card-title"><a href="../guides/claw-a2v-space/">Подключение claw.a2v.space (OpenClaw)</a></h3>
<p class="card-text"><h2 id="архитектура">Архитектура</h2>
<pre tabindex="0"><code>Mac Studio (192.168.0.37:18789)
→ autossh SSH-туннель
→ VPS 95.163.232.9:8080
→ nginx HTTPS
→ https://claw.a2v.space
</code></pre><h2 id="шаги-настройки">Шаги настройки</h2>
<h3 id="1-dns">1. DNS</h3>
<p>A-запись <code>claw.a2v.space</code> → <code>95.163.232.9</code></p>
<p>NS-серверы: <code>ns1.hosting.reg.ru</code>, <code>ns2.hosting.reg.ru</code></p>
<h3 id="2-mac-studio--openclaw">2. Mac Studio — OpenClaw</h3>
<ul>
<li>Порт: 18789</li>
<li>Конфиг: <code>~/.openclaw/openclaw.json</code></li>
</ul>
<h3 id="3-ssh-туннель-launchd">3. SSH-туннель (launchd)</h3>
<p>Plist: <code>~/Library/LaunchAgents/com.openclaw.sshtunnel.plist</code></p>
<p>Ключевой флаг: <code>-R 8080:localhost:18789</code></p>
<h3 id="4-vps--nginx-конфиг">4. VPS — nginx конфиг</h3>
<p>SSL сертификат: <code>/etc/letsencrypt/live/sand.a2v.space/</code></p>
<h2 id="nginx-конфиг">nginx конфиг</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-nginx" data-lang="nginx"><span style="display:flex;"><span><span style="color:#66d9ef">server</span> {
</span></span><span style="display:flex;"><span> <span style="color:#f92672">listen</span> <span style="color:#ae81ff">80</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">server_name</span> <span style="color:#e6db74">claw.a2v.space</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">server_name</span> <span style="color:#e6db74">sand.a2v.space</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">return</span> <span style="color:#ae81ff">301</span> <span style="color:#e6db74">https://</span>$server_name$request_uri;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">server</span> {
</span></span><span style="display:flex;"><span> <span style="color:#f92672">listen</span> <span style="color:#ae81ff">443</span> <span style="color:#e6db74">ssl</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">server_name</span> <span style="color:#e6db74">claw.a2v.space</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">server_name</span> <span style="color:#e6db74">sand.a2v.space</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">ssl_certificate</span> <span style="color:#e6db74">/etc/letsencrypt/live/claw.a2v.space/fullchain.pem</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">ssl_certificate_key</span> <span style="color:#e6db74">/etc/letsencrypt/live/claw.a2v.space/privkey.pem</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">ssl_certificate</span> <span style="color:#e6db74">/etc/letsencrypt/live/sand.a2v.space/fullchain.pem</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">ssl_certificate_key</span> <span style="color:#e6db74">/etc/letsencrypt/live/sand.a2v.space/privkey.pem</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">location</span> <span style="color:#e6db74">/api</span> {
</span></span><span style="display:flex;"><span> <span style="color:#f92672">proxy_pass</span> <span style="color:#e6db74">http://127.0.0.1:8083</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">proxy_set_header</span> <span style="color:#e6db74">Host</span> $host;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">proxy_set_header</span> <span style="color:#e6db74">X-Real-IP</span> $remote_addr;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">proxy_set_header</span> <span style="color:#e6db74">X-Forwarded-For</span> $proxy_add_x_forwarded_for;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">proxy_set_header</span> <span style="color:#e6db74">X-Forwarded-Proto</span> $scheme;
</span></span><span style="display:flex;"><span> }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">location</span> <span style="color:#e6db74">/</span> {
</span></span><span style="display:flex;"><span> <span style="color:#f92672">proxy_pass</span> <span style="color:#e6db74">http://127.0.0.1:8080</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">proxy_pass</span> <span style="color:#e6db74">http://127.0.0.1:8082</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">proxy_set_header</span> <span style="color:#e6db74">Host</span> $host;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">proxy_set_header</span> <span style="color:#e6db74">X-Real-IP</span> $remote_addr;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">proxy_set_header</span> <span style="color:#e6db74">X-Forwarded-For</span> $proxy_add_x_forwarded_for;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">proxy_set_header</span> <span style="color:#e6db74">X-Forwarded-Proto</span> $scheme;
</span></span><span style="display:flex;"><span> }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h3 id="5-ssl-сертификат">5. SSL-сертификат</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>certbot certonly --nginx -d claw.a2v.space
</span></span></code></pre></div><h3 id="6-openclaw-config">6. OpenClaw config</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span> <span style="color:#f92672">&#34;allowedOrigins&#34;</span>: [<span style="color:#e6db74">&#34;https://claw.a2v.space&#34;</span>],
</span></span><span style="display:flex;"><span> <span style="color:#f92672">&#34;trustedProxies&#34;</span>: [<span style="color:#e6db74">&#34;127.0.0.1&#34;</span>]
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div></p>
</span></span></code></pre></div><h2 id="база-данных">База данных</h2>
<p>PostgreSQL 16 в Docker через Colima:</p></p>
<div class="tags">
<a href="../tags/openclaw/" class="tag">openclaw</a>
<a href="../tags/angular/" class="tag">angular</a>
<a href="../tags/ssh/" class="tag">ssh</a>
<a href="../tags/go/" class="tag">go</a>
<a href="../tags/docker/" class="tag">docker</a>
<a href="../tags/nginx/" class="tag">nginx</a>
@@ -534,82 +377,61 @@
<div class="col-md-6 mb-4">
<div class="card h-100">
<div class="card-body">
<h3 class="card-title"><a href="../guides/sand-a2v-space/">Подключение sand.a2v.space (Leadera Project)</a></h3>
<h3 class="card-title"><a href="../guides/claw-a2v-space/">Подключение claw.a2v.space (OpenClaw)</a></h3>
<p class="card-text"><h2 id="архитектура">Архитектура</h2>
<pre tabindex="0"><code>Mac Studio
├─ Frontend (Angular) :4200 (pm2: leadera-fe)
├─ Backend (Go) :8080 (pm2: leadera-api)
└─ PostgreSQL 16 в Docker (Colima, container: app-leadera-db)
→ autossh SSH-туннель (-R 8082:localhost:4200 -R 8083:localhost:8080)
→ VPS 95.163.232.9
<pre tabindex="0"><code>Mac Studio (192.168.0.37:18789)
→ autossh SSH-туннель
→ VPS 95.163.232.9:8080
→ nginx HTTPS
→ https://sand.a2v.space
</code></pre><h2 id="параметры">Параметры</h2>
<table>
<thead>
<tr>
<th>Компонент</th>
<th>Локальный порт</th>
<th>Туннель порт</th>
<th>pm2 имя</th>
</tr>
</thead>
<tbody>
<tr>
<td>Frontend (Angular)</td>
<td>4200</td>
<td>8082</td>
<td>leadera-fe</td>
</tr>
<tr>
<td>Backend (Go)</td>
<td>8080</td>
<td>8083</td>
<td>leadera-api</td>
</tr>
</tbody>
</table>
<p>SSL сертификат: <code>/etc/letsencrypt/live/sand.a2v.space/</code></p>
<h2 id="nginx-конфиг">nginx конфиг</h2>
→ https://claw.a2v.space
</code></pre><h2 id="шаги-настройки">Шаги настройки</h2>
<h3 id="1-dns">1. DNS</h3>
<p>A-запись <code>claw.a2v.space</code> → <code>95.163.232.9</code></p>
<p>NS-серверы: <code>ns1.hosting.reg.ru</code>, <code>ns2.hosting.reg.ru</code></p>
<h3 id="2-mac-studio--openclaw">2. Mac Studio — OpenClaw</h3>
<ul>
<li>Порт: 18789</li>
<li>Конфиг: <code>~/.openclaw/openclaw.json</code></li>
</ul>
<h3 id="3-ssh-туннель-launchd">3. SSH-туннель (launchd)</h3>
<p>Plist: <code>~/Library/LaunchAgents/com.openclaw.sshtunnel.plist</code></p>
<p>Ключевой флаг: <code>-R 8080:localhost:18789</code></p>
<h3 id="4-vps--nginx-конфиг">4. VPS — nginx конфиг</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-nginx" data-lang="nginx"><span style="display:flex;"><span><span style="color:#66d9ef">server</span> {
</span></span><span style="display:flex;"><span> <span style="color:#f92672">listen</span> <span style="color:#ae81ff">80</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">server_name</span> <span style="color:#e6db74">sand.a2v.space</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">server_name</span> <span style="color:#e6db74">claw.a2v.space</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">return</span> <span style="color:#ae81ff">301</span> <span style="color:#e6db74">https://</span>$server_name$request_uri;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">server</span> {
</span></span><span style="display:flex;"><span> <span style="color:#f92672">listen</span> <span style="color:#ae81ff">443</span> <span style="color:#e6db74">ssl</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">server_name</span> <span style="color:#e6db74">sand.a2v.space</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">server_name</span> <span style="color:#e6db74">claw.a2v.space</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">ssl_certificate</span> <span style="color:#e6db74">/etc/letsencrypt/live/sand.a2v.space/fullchain.pem</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">ssl_certificate_key</span> <span style="color:#e6db74">/etc/letsencrypt/live/sand.a2v.space/privkey.pem</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">location</span> <span style="color:#e6db74">/api</span> {
</span></span><span style="display:flex;"><span> <span style="color:#f92672">proxy_pass</span> <span style="color:#e6db74">http://127.0.0.1:8083</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">proxy_set_header</span> <span style="color:#e6db74">Host</span> $host;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">proxy_set_header</span> <span style="color:#e6db74">X-Real-IP</span> $remote_addr;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">proxy_set_header</span> <span style="color:#e6db74">X-Forwarded-For</span> $proxy_add_x_forwarded_for;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">proxy_set_header</span> <span style="color:#e6db74">X-Forwarded-Proto</span> $scheme;
</span></span><span style="display:flex;"><span> }
</span></span><span style="display:flex;"><span> <span style="color:#f92672">ssl_certificate</span> <span style="color:#e6db74">/etc/letsencrypt/live/claw.a2v.space/fullchain.pem</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">ssl_certificate_key</span> <span style="color:#e6db74">/etc/letsencrypt/live/claw.a2v.space/privkey.pem</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">location</span> <span style="color:#e6db74">/</span> {
</span></span><span style="display:flex;"><span> <span style="color:#f92672">proxy_pass</span> <span style="color:#e6db74">http://127.0.0.1:8082</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">proxy_pass</span> <span style="color:#e6db74">http://127.0.0.1:8080</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">proxy_set_header</span> <span style="color:#e6db74">Host</span> $host;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">proxy_set_header</span> <span style="color:#e6db74">X-Real-IP</span> $remote_addr;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">proxy_set_header</span> <span style="color:#e6db74">X-Forwarded-For</span> $proxy_add_x_forwarded_for;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">proxy_set_header</span> <span style="color:#e6db74">X-Forwarded-Proto</span> $scheme;
</span></span><span style="display:flex;"><span> }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="база-данных">База данных</h2>
<p>PostgreSQL 16 в Docker через Colima:</p></p>
</span></span></code></pre></div><h3 id="5-ssl-сертификат">5. SSL-сертификат</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>certbot certonly --nginx -d claw.a2v.space
</span></span></code></pre></div><h3 id="6-openclaw-config">6. OpenClaw config</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span> <span style="color:#f92672">&#34;allowedOrigins&#34;</span>: [<span style="color:#e6db74">&#34;https://claw.a2v.space&#34;</span>],
</span></span><span style="display:flex;"><span> <span style="color:#f92672">&#34;trustedProxies&#34;</span>: [<span style="color:#e6db74">&#34;127.0.0.1&#34;</span>]
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div></p>
<div class="tags">
<a href="../tags/angular/" class="tag">angular</a>
<a href="../tags/openclaw/" class="tag">openclaw</a>
<a href="../tags/go/" class="tag">go</a>
<a href="../tags/docker/" class="tag">docker</a>
<a href="../tags/ssh/" class="tag">ssh</a>
<a href="../tags/nginx/" class="tag">nginx</a>
@@ -623,6 +445,113 @@
</div>
</div>
<div class="col-md-6 mb-4">
<div class="card h-100">
<div class="card-body">
<h3 class="card-title"><a href="../guides/vps-reverse-proxy/">Настройка VPS как реверс-прокси</a></h3>
<p class="card-text"><h2 id="общая-схема">Общая схема</h2>
<pre tabindex="0"><code>Mac Studio (локальная сеть)
→ autossh (SSH-туннели)
→ VPS 95.163.232.9 (Debian)
→ nginx (HTTPS reverse proxy)
→ интернет
</code></pre><h2 id="что-нужно-на-vps">Что нужно на VPS</h2>
<h3 id="1-установленные-пакеты">1. Установленные пакеты</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>apt update
</span></span><span style="display:flex;"><span>apt install nginx certbot python3-certbot-nginx
</span></span></code></pre></div><h3 id="2-ssh-доступ">2. SSH-доступ</h3>
<ul>
<li>Авторизация только по ключам</li>
<li>Публичный ключ с Mac Studio добавлен в <code>/root/.ssh/authorized_keys</code></li>
</ul>
<h3 id="3-nginx">3. nginx</h3>
<p>Для каждого домена создать server block:</p>
<ul>
<li>HTTP → редирект на HTTPS</li>
<li>HTTPS с SSL-сертификатом Let&rsquo;s Encrypt</li>
<li><code>proxy_pass</code> на localhost-порт туннеля</li>
</ul>
<p>Пример структуры:</p></p>
<div class="tags">
<a href="../tags/vps/" class="tag">vps</a>
<a href="../tags/nginx/" class="tag">nginx</a>
<a href="../tags/ssh/" class="tag">ssh</a>
<a href="../tags/reverse-proxy/" class="tag">reverse-proxy</a>
<a href="../tags/devops/" class="tag">devops</a>
</div>
</div>
</div>
</div>
<div class="col-md-6 mb-4">
<div class="card h-100">
<div class="card-body">
<h3 class="card-title"><a href="../guides/ssh-tunnels-vps/">SSH туннели для VPS reverse proxy</a></h3>
<p class="card-text"><h2 id="настройка-ssh-туннелей">Настройка SSH туннелей</h2>
<h3 id="vps-regru-951632329">VPS reg.ru (95.163.232.9)</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e"># На Mac Studio: создать туннель для каждого сервиса</span>
</span></span><span style="display:flex;"><span>ssh -N -R 8080:localhost:8080 root@95.163.232.9 <span style="color:#75715e"># leadera-api</span>
</span></span><span style="display:flex;"><span>ssh -N -R 8081:localhost:4096 root@95.163.232.9 <span style="color:#75715e"># opencode</span>
</span></span><span style="display:flex;"><span>ssh -N -R 8082:localhost:4200 root@95.163.232.9 <span style="color:#75715e"># leadera-fe</span>
</span></span><span style="display:flex;"><span>ssh -N -R 8083:localhost:8080 root@95.163.232.9 <span style="color:#75715e"># docs-a2v</span>
</span></span></code></pre></div><h3 id="настройка-launchd-plist">Настройка launchd plist</h3>
<p><strong>Файл</strong>: <code>~/Library/LaunchAgents/com.openclaw.sshtunnel.plist</code></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#75715e">&lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34;?&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">&lt;!DOCTYPE plist PUBLIC &#34;-//Apple//DTD PLIST 1.0//EN&#34; &#34;http://www.apple.com/DTDs/PropertyList-1.0.dtd&#34;&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;plist</span> <span style="color:#a6e22e">version=</span><span style="color:#e6db74">&#34;1.0&#34;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;dict&gt;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">&lt;key&gt;</span>Label<span style="color:#f92672">&lt;/key&gt;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">&lt;string&gt;</span>com.openclaw.sshtunnel<span style="color:#f92672">&lt;/string&gt;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">&lt;key&gt;</span>ProgramArguments<span style="color:#f92672">&lt;/key&gt;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">&lt;array&gt;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">&lt;string&gt;</span>ssh<span style="color:#f92672">&lt;/string&gt;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">&lt;string&gt;</span>-N<span style="color:#f92672">&lt;/string&gt;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">&lt;string&gt;</span>-R<span style="color:#f92672">&lt;/string&gt;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">&lt;string&gt;</span>8080:localhost:8080<span style="color:#f92672">&lt;/string&gt;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">&lt;string&gt;</span>root@95.163.232.9<span style="color:#f92672">&lt;/string&gt;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">&lt;/array&gt;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">&lt;key&gt;</span>RunAtLoad<span style="color:#f92672">&lt;/key&gt;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">&lt;true/&gt;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">&lt;key&gt;</span>KeepAlive<span style="color:#f92672">&lt;/key&gt;</span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">&lt;true/&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/dict&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/plist&gt;</span>
</span></span></code></pre></div><h3 id="автозапуск">Автозапуск</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e"># Загрузить plist</span>
</span></span><span style="display:flex;"><span>launchctl load ~/Library/LaunchAgents/com.openclaw.sshtunnel.plist
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Проверить статус</span>
</span></span><span style="display:flex;"><span>launchctl list | grep sshtunnel
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Удалить (при необходимости)</span>
</span></span><span style="display:flex;"><span>launchctl unload ~/Library/LaunchAgents/com.openclaw.sshtunnel.plist
</span></span></code></pre></div><h2 id="доступ-к-сервисам">Доступ к сервисам</h2>
<p>Через reverse proxy на VPS:</p></p>
<div class="tags">
<a href="../tags/ssh/" class="tag">ssh</a>
<a href="../tags/tunnel/" class="tag">tunnel</a>
<a href="../tags/vps/" class="tag">vps</a>
<a href="../tags/reverse-proxy/" class="tag">reverse-proxy</a>
</div>
</div>
</div>
</div>
</div>
</div>