1 Какво е това накратко?
Система за правене на уебсайтове. Състои се от две части:
Go Backend (бекенд)
Админ панел, където редактираш съдържание. Написан на езика Go. Компилира се до един файл. Пази данните в SQLite — обикновен файл на диска, не е нужен отделен database сървър.
Astro Frontend (фронтенд)
Генератор за сайта. Взема данните от Go и създава готови HTML файлове. Написан на JavaScript/Astro. Работи само при "Build" — после спира.
💡 Ключовата идея
Публичният сайт са готови HTML файлове. Когато посетител отвори сайта, се чете файл от диска — никакъв код не се изпълнява. Не работи нито Go, нито Node.js, нито PHP, нито нищо друго. Само nginx подава файла.
2 Кои програми участват?
| Програма |
Какво прави |
Кога работи |
RAM |
| nginx |
Подава HTML файлове на посетители. Пренасочва /admin и /api заявки към Go. |
Винаги |
~5 MB |
| systemd |
Слуша порта на Go. Когато дойде заявка — буди Go. |
Винаги (част от Linux) |
~0 MB (вече работи) |
| Go CMS |
Админ панел, обработка на форми, API, стартиране на build. |
Само при заявка. Спи след 2 мин. |
~20 MB (когато работи) |
| Node.js / Astro |
Генерира HTML файлове от данните. |
Само при Build. Секунди, после спира. |
~100 MB (само при build) |
| SQLite |
Базата данни. Просто файл — site.db |
Не е програма. Файл на диска. |
0 MB |
⏰ 99% от времето
Работи САМО nginx (~5 MB). Всичко останало спи. Ако имаш 20 сайта на сървъра — пак само nginx работи, защото всички Go процеси спят. Общо ~5 MB RAM за 20 сайта.
3 Какво трябва на сървъра?
| Софтуер |
За какво |
Как се инсталира |
| nginx |
Уеб сървър (подава файлове, proxy) |
apt install nginx |
| Node.js |
Нужен за Astro build (генериране на HTML) |
apt install nodejs npm |
| rsync |
Копира генерираните файлове в публичната папка |
apt install rsync |
| systemd |
Управлява Go процеса (буди/спира) |
Вече е на всеки Linux |
❓ Трябва ли Go compiler на сървъра?
Не задължително. Go binary-то може да се компилира на друг компютър и да се копира готово. Компилираш на лаптопа си с GOOS=linux go build и качваш 1 файл. Но ако имаш Go на сървъра — може и там.
❓ Трябва ли Node.js да работи постоянно?
НЕ. Node.js се стартира САМО когато админът натисне "Build". Работи 5-30 секунди (генерира HTML файловете) и спира. Не работи постоянно. Не яде RAM когато не се ползва.
❓ Трябва ли Docker?
НЕ. Няма Docker, няма контейнери. Всичко работи директно на операционната система.
❓ Трябва ли отделен database сървър?
НЕ. Базата данни е SQLite — един файл (site.db) вътре в папката на проекта. Няма MySQL, PostgreSQL, нищо друго. Файлът може да се копира на USB, по email — това е цялата база.
4 Какво се случва при различни ситуации
Ситуация А: Посетител отваря страница
Някой пише https://example.com/about в браузъра.
Браузърът праща заявка към nginx
nginx получава: "Искам /about"
nginx проверява правилата си
/about — не започва с /admin или /api → значи е статичен файл
nginx търси файла на диска
Търси: public_html/about/index.html → Намерен!
nginx връща файла
HTML файлът отива при браузъра. Готово.
Време: < 5ms
Go: Не участва. Не се буди. Не знае.
Node.js: Не участва. Не се буди. Не знае.
RAM: 0 допълнителна (nginx вече работи)
Ситуация Б: Посетител праща контактна форма
Посетител попълва форма за контакт и натиска "Изпрати".
Браузърът праща POST заявка
POST /api/form/contact с данни от формата (име, имейл, съобщение)
nginx получава заявката
/api/* → не е статичен файл, трябва Go. Пренасочва към порт 8080.
systemd буди Go
systemd слуша порт 8080. Вижда връзка → стартира Go binary-то. Отнема ~100ms (0.1 секунда). Посетителят не усеща забавяне.
Go обработва формата
Проверява rate limit (макс 1 заявка на 30 сек от един IP). Записва данните в SQLite таблица "submissions".
Go връща отговор
{"ok": "saved"} → Браузърът показва "Съобщението е изпратено!"
Go чака 120 секунди...
Ако няма нови заявки за 2 минути → Go спира сам → 0 RAM, 0 CPU. Ако дойде нова заявка → таймерът се нулира.
✅ Формите работят дори когато Go спи!
systemd автоматично буди Go при заявка. Посетителят не знае, че Go е спял. Вижда нормална бърза реакция.
Ситуация В: Админът влиза в панела
Админът отваря https://example.com/admin/
nginx получава /admin/ заявка
/admin/* → пренасочва към порт 8080
systemd буди Go (ако спи)
Go стартира за ~100ms. Ако вече работи — стъпката се пропуска.
Go проверява дали е логнат
Търси JWT cookie в браузъра. Няма cookie → показва login страница.
Админът въвежда потребител и парола
Go проверява с bcrypt (защитен алгоритъм за пароли). Ако е правилно → създава JWT token и го записва в cookie.
Админът вижда Dashboard
Списък с всички страници. Може да създава, редактира, трие.
Докато админът работи (кликва, навигира) — всяко действие нулира idle таймера. Go не спи докато някой го ползва.
Ситуация Г: Админът редактира и публикува страница
Админът отваря страница за редакция
/admin/edit/5 → Go зарежда страница #5 от SQLite и показва формата.
Админът променя съдържанието и натиска Save
Go записва промените в SQLite. Маркира страницата: needs_rebuild = 1 (трябва rebuild).
Админът натиска Build
Go проверява кои страници имат needs_rebuild = 1.
Go стартира Astro build
Изпълнява командата npx astro build с указание кои страници да се генерират. Node.js стартира, Astro работи.
Astro генерира HTML файлове
Astro пита Go API: "Дай ми данните за всички страници" → Go връща JSON → Astro създава HTML файлове САМО за променените страници.
rsync копира файловете
Новите HTML файлове се копират в public_html/ (без да се трият останалите).
Готово!
Node.js спира. Go маркира страниците: needs_rebuild = 0. Посетителите вече виждат новото съдържание.
⚡ Selective Build — защо е бързо
Ако имаш 50 страници и промениш само 2 — Astro генерира САМО тези 2. Не ги прави всичките 50. Затова отнема 5 секунди вместо 30+.
Full rebuild (бутон "Full rebuild") генерира ВСИЧКИ страници. Ползва се при промяна на дизайн или при начален deploy.
5 Как точно работи "заспиването"
Това е най-важната функционалност. Ето я подробно:
Какво е systemd socket activation?
Вместо Go да слуша порт 8080 постоянно (и да яде RAM), systemd (вградена програма в Linux) слуша вместо него. Когато дойде заявка — systemd стартира Go и му подава връзката.
Конфигурация — 2 файла:
cms.socket — казва на systemd: "Слушай порт 8080"
┌──────────────────────────────────────┐
│ [Socket] │
│ ListenStream=127.0.0.1:8080 │
│ Accept=no │
└──────────────────────────────────────┘
cms.service — казва на systemd: "Когато дойде връзка, стартирай това"
┌──────────────────────────────────────┐
│ [Service] │
│ ExecStart=/var/www/.../backend/cms │
│ Restart=on-failure │
└──────────────────────────────────────┘
Idle timeout — как Go решава кога да спре
Таймлайн:
0:00 Заявка пристига → systemd буди Go → таймер: 120 сек
0:05 Нова заявка → таймер НУЛИРАН: 120 сек
0:30 Нова заявка → таймер НУЛИРАН: 120 сек
0:45 Нова заявка → таймер НУЛИРАН: 120 сек
...
5:00 Последната заявка → таймер: 120 сек
5:30 ... тишина ... таймер: 90 сек
6:00 ... тишина ... таймер: 60 сек
6:30 ... тишина ... таймер: 30 сек
7:00 120 сек без заявки → Go СПИРА → 0 RAM, 0 CPU
... (часове/дни по-късно)
Нова заявка → systemd буди Go → работи отново
Специален случай: Build
Ако Go стартира Astro build (5-30 секунди), idle таймерът се паузира. Иначе може Go да спре по средата на build-а. След build-а — таймерът се възобновява.
6 Файлова структура
Цялият проект живее в една папка. Ето какво има вътре:
/var/www/example.com/
│
├── backend/
│ ├── main.go
│ ├── server.go
│ ├── db.go
│ ├── auth.go
│ ├── admin.go
│ ├── api.go
│ ├── build.go
│ ├── media.go
│ ├── public.go
│ ├── cms
│ └── embed/
│ ├── templates/
│ └── static/
│
├── frontend/
│ ├── astro.config.mjs
│ ├── package.json
│ └── src/
│ ├── pages/
│ ├── blocks/
│ └── layouts/
│
├── data/
│ └── site.db
│
├── public_html/
│ ├── index.html
│ ├── about/index.html
│ ├── contacts/index.html
│ └── images/uploads/
│
└── deploy/
├── setup.sh
├── cms.socket
├── cms.service
└── nginx.conf
7 Кой процес кога работи
| Ситуация |
nginx |
Go CMS |
Node/Astro |
SQLite |
| Посетител чете страница |
✅ сервира HTML |
💤 спи |
💤 спи |
— файл |
| Посетител праща форма |
✅ proxy |
✅ буди се |
💤 спи |
✅ пише |
| Админ влиза |
✅ proxy |
✅ буди се |
💤 спи |
✅ чете |
| Админ запазва страница |
✅ proxy |
✅ работи |
💤 спи |
✅ пише |
| Админ натиска Build |
✅ proxy |
✅ стартира build |
✅ билдва HTML |
✅ Go чете |
| Покой (99% от времето) |
✅ слуша |
❌ не съществува |
❌ не съществува |
— файл |
8 Пълна схема
СЪРВЪР
┌─────────────────────────────────────────────────────────────────┐
│ │
│ ┌──────────┐ ┌─────────────────────────────────────────┐ │
│ │ │ │ nginx (винаги работи) │ │
│ │ Посетител├────►│ │ │
│ │ │ │ /* ──► public_html/ (статични HTML) │ │
│ └──────────┘ │ │ │
│ │ /admin/* ──┐ │ │
│ ┌──────────┐ │ /api/* ──┤ proxy към порт 8080 │ │
│ │ │ └─────────────┼───────────────────────────┘ │
│ │ Админ ├──────────────────►│ │
│ │ │ ▼ │
│ └──────────┘ ┌─────────────────────────────────────────┐ │
│ │ systemd (слуша порт 8080) │ │
│ │ │ │
│ │ Заявка? ──► Стартирай Go binary │ │
│ └──────────────────┬──────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────┐ │
│ │ Go CMS (on-demand) │ │
│ │ │ │
│ │ • Админ панел (login, edit, save) │ │
│ │ • API (данни за Astro) │ │
│ │ • Форми (contact, newsletter) │ │
│ │ • Media upload │ │
│ │ • Build trigger │ │
│ │ │ │
│ │ SQLite: data/site.db │ │
│ │ │ │
│ │ Idle 120 сек → СПИРА │ │
│ └──────────────────┬──────────────────────┘ │
│ │ │
│ (при Build) │ │
│ ▼ │
│ ┌─────────────────────────────────────────┐ │
│ │ Node.js / Astro (при build) │ │
│ │ │ │
│ │ 1. Fetch данни от Go API │ │
│ │ 2. Генерирай HTML файлове │ │
│ │ 3. rsync → public_html/ │ │
│ │ 4. СПРИ (готово) │ │
│ └─────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
9 Инсталация от нулата
Стъпка 1: Подготви сървъра
$ apt update
$ apt install nginx nodejs npm rsync
$ nginx -v
$ node --version
Стъпка 2: Копирай проекта на сървъра
$ scp -r project/ root@server:/var/www/example.com/
Стъпка 3: Компилирай Go binary
$ cd /var/www/example.com/backend
$ go build -o cms .
$ GOOS=linux GOARCH=amd64 go build -o cms .
$ scp cms root@server:/var/www/example.com/backend/
Стъпка 4: Инсталирай Node зависимости
$ cd /var/www/example.com/frontend
$ npm install
Стъпка 5: Пусни setup.sh
$ cd /var/www/example.com/deploy
$ ./setup.sh example.com 8080
Стъпка 6: SSL сертификат
$ certbot --nginx -d example.com
Стъпка 7: Влез в админа
Отвори: https://example.com/admin/
Login: admin / admin123
10 Преместване на друг сървър
Копирай цялата папка
scp -r /var/www/example.com/ root@new-server:/var/www/
Всичко е вътре: код, база данни, качени файлове, генериран сайт.
На новия сървър: инсталирай nginx, node, rsync
apt install nginx nodejs npm rsync
Пусни setup.sh
cd deploy && ./setup.sh example.com 8080
Готово
Сайтът работи на новия сървър. Същите данни, същите потребители, всичко.
11 Множество сайтове на един сървър
Сайт Порт systemd socket
─────────────────────── ────── ─────────────────────────
example.com 8080 example-com-cms.socket
portfolio.bg 8081 portfolio-bg-cms.socket
shop.store 8082 shop-store-cms.socket
gallery.art 8083 gallery-art-cms.socket
Всеки сайт има собствена:
• Папка (/var/www/domain/)
• Go binary
• SQLite база
• Astro frontend
• nginx конфигурация
• systemd socket + service
В покой: ВСИЧКИ Go процеси спят.
RAM = само nginx ≈ 5 MB за ВСИЧКИ сайтове.
12 Блок система (секции)
Съдържанието на всяка страница се състои от блокове (секции). Всеки блок е визуален елемент:
| Блок |
Описание |
Файл |
| hero |
Голям банер с заглавие, подзаглавие, фоново изображение |
WfHero.astro |
| text |
Текстов блок с HTML съдържание |
WfText.astro |
| image |
Картинка с описание |
WfImage.astro |
| gallery |
Мрежа от картинки (галерия) |
WfGallery.astro |
| contact |
Контактна форма (име, имейл, съобщение) |
WfContact.astro |
В базата данни блоковете се пазят като JSON:
[
{
"type": "hero",
"data": {
"title": "Добре дошли",
"image": "/images/uploads/hero.jpg"
}
},
{
"type": "text",
"data": {
"content": "<p>Ние сме компания...</p>"
}
},
{
"type": "gallery",
"data": {
"images": [
{ "url": "/images/uploads/1.jpg" },
{ "url": "/images/uploads/2.jpg" }
]
}
}
]
Добавяне на нов тип блок:
- Създай
frontend/src/blocks/WfNewBlock.astro
- Импортирай го в
WfRender.astro
- Ползвай го в страница:
{"type": "newblock", "data": {...}}
Обобщение
Един Go binary + Astro за генерация на HTML + nginx за сервиране + systemd за on-demand стартиране. Нищо не работи когато не се ползва. Всичко е в една папка. Мести се с scp.
Нужен софтуер: nginx, Node.js, rsync, systemd
НЕ трябва: Docker, MySQL, Go compiler*, PHP, Redis, или нещо друго
* Go compiler трябва само за компилация на binary-то. Може да се направи на друг компютър.