🔒 Repository is read-only – file editing is disabled.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575
#!/bin/bash
# =============================================================================
# PaganOS Web v2 – Full Auto-Installer
# bash install.sh [--domain paganlinux.eu] [--email admin@paganlinux.eu]
# Wysyłasz z pagan-web-v2/, wpisujesz bash install.sh i wszystko samo działa.
# =============================================================================
set -euo pipefail
# ── Kolory ──
G='\033[32m'; C='\033[36m'; R='\033[31m'; Y='\033[33m'; B='\033[1m'; N='\033[0m'
banner() { echo -e "${C}═══ $* ${N}"; }
ok() { echo -e " ${G}✅${N} $*"; }
warn() { echo -e " ${Y}⚠${N} $*"; }
err() { echo -e " ${R}❌${N} $*"; }
# ── Opcje ──
DOMAIN="${DOMAIN:-paganlinux.eu}"
EMAIL="${EMAIL:-admin@paganlinux.eu}"
SETUP_SSL="${SETUP_SSL:-yes}"
SETUP_FIREWALL="${SETUP_FIREWALL:-yes}"
GPG_KEY_ID="${GPG_KEY_ID:-}"
while [[ $# -gt 0 ]]; do
case "$1" in
--domain) DOMAIN="$2"; shift 2 ;;
--email) EMAIL="$2"; shift 2 ;;
--no-ssl) SETUP_SSL="no"; shift ;;
--no-fw) SETUP_FIREWALL="no"; shift ;;
--gpg-key) GPG_KEY_ID="$2"; shift 2 ;;
-h|--help)
echo "Użycie: bash install.sh [opcje]"
echo " --domain DOMAIN Domena główna (domyślnie: paganlinux.eu)"
echo " --email EMAIL Email do Let's Encrypt"
echo " --no-ssl Pomiń SSL/Certbot"
echo " --no-fw Pomiń firewall"
echo " --gpg-key KEYID ID klucza GPG do podpisywania pakietów"
exit 0 ;;
*) echo "Nieznana opcja: $1"; exit 1 ;;
esac
done
# ── Root check ──
if [[ $EUID -ne 0 ]]; then
echo -e "${R}❌ Musisz uruchomić jako root: sudo bash install.sh${N}"
exit 1
fi
echo -e "${C}"
echo "╔══════════════════════════════════════════════════╗"
echo "║ PaganOS Web v2 – Pełna Instalacja ║"
echo "║ Domena: $DOMAIN"
echo "║ SSL: $SETUP_SSL | FW: $SETUP_FIREWALL"
echo "╚══════════════════════════════════════════════════╝"
echo -e "${N}"
SRC="$(dirname "$(readlink -f "$0")")"
DST="/opt/pagan-web-v2"
# ═══════════════════════════════════════════════════════════════
# 1. Pakiety systemowe
# ═══════════════════════════════════════════════════════════════
banner "1/7 – Pakiety systemowe"
install_pkg() {
if command -v apt &>/dev/null; then
DEBIAN_FRONTEND=noninteractive apt install -y -qq "$@" 2>/dev/null || apt install -y "$@"
elif command -v pacman &>/dev/null; then
pacman -Sy --noconfirm "$@" 2>/dev/null || true
elif command -v dnf &>/dev/null; then
dnf install -y "$@" 2>/dev/null || true
else
warn "Nieznany menedżer pakietów – zainstaluj ręcznie: $*"
fi
}
install_pkg python3 python3-pip git nginx sqlite3 curl certbot python3-certbot-nginx ufw
pip3 install --break-system-packages flask pygments requests pyyaml mistune 2>/dev/null || \
pip3 install flask pygments requests pyyaml mistune 2>/dev/null || true
ok "Pakiety gotowe"
# ═══════════════════════════════════════════════════════════════
# 2. Kopiowanie aplikacji
# ═══════════════════════════════════════════════════════════════
banner "2/7 – Kopiowanie aplikacji do $DST"
if [ "$SRC" != "$DST" ]; then
rm -rf "$DST"
cp -r "$SRC" "$DST"
ok "Skopiowano → $DST"
else
ok "Już w $DST"
fi
# Nadaj uprawnienia wykonywalne
chmod +x "$DST/app.py" "$DST/pagbuild" "$DST/pagsync" "$DST/pag" 2>/dev/null || true
# ═══════════════════════════════════════════════════════════════
# 3. Katalogi i symlinki
# ═══════════════════════════════════════════════════════════════
banner "3/7 – Katalogi i struktura"
mkdir -p /var/lib/pagan-web
mkdir -p /var/lib/pagan-sync
mkdir -p /var/lib/pagan-build/rootfs
mkdir -p /var/cache/pagbuild/{sources,output}
mkdir -p /var/git
mkdir -p /var/www/repo.paganlinux.eu/stable
mkdir -p /var/www/repo.paganlinux.eu/sources
mkdir -p /etc/pagan
# Symlink recipes
if [ ! -d "/var/lib/pagan-sync/recipes/core" ]; then
RECIPES_SRC="$(readlink -f "$SRC/../recipes")"
if [ -d "$RECIPES_SRC" ]; then
ln -sf "$RECIPES_SRC" /var/lib/pagan-sync/recipes
ok "recipes → $(basename "$RECIPES_SRC") (symlink)"
else
mkdir -p /var/lib/pagan-sync/recipes
warn "Brak katalogu recipes/ obok pagan-web-v2/ – utworzono pusty"
fi
else
ok "recipes już istnieje"
fi
# Symlink narzędzi do /usr/bin
ln -sf "$DST/pagbuild" /usr/bin/pagbuild 2>/dev/null || true
ln -sf "$DST/pagsync" /usr/bin/pagsync 2>/dev/null || true
ln -sf "$DST/pag" /usr/bin/pag 2>/dev/null || true
ok "Symlinki: pagbuild, pagsync, pag → /usr/bin"
# ═══════════════════════════════════════════════════════════════
# 4. GPG – klucz do podpisywania pakietów
# ═══════════════════════════════════════════════════════════════
banner "4/7 – GPG (podpisywanie pakietów)"
if [[ -n "$GPG_KEY_ID" ]]; then
echo "PAGAN_DO_SIGN=1" > /etc/pagan/build.conf
echo "PAGAN_GPG_KEY=$GPG_KEY_ID" >> /etc/pagan/build.conf
ok "GPG: klucz $GPG_KEY_ID – podpisywanie włączone"
elif gpg --list-secret-keys 2>/dev/null | grep -q "^sec"; then
KEY_ID=$(gpg --list-secret-keys --with-colons 2>/dev/null | grep "^sec:" | head -1 | cut -d: -f5)
echo "PAGAN_DO_SIGN=1" > /etc/pagan/build.conf
echo "PAGAN_GPG_KEY=$KEY_ID" >> /etc/pagan/build.conf
ok "GPG: wykryto klucz $KEY_ID – podpisywanie włączone"
else
echo "PAGAN_DO_SIGN=0" > /etc/pagan/build.conf
warn "Brak klucza GPG – podpisywanie wyłączone"
warn "Wygeneruj: gpg --gen-key | potem: bash install.sh --gpg-key KLUCZ"
fi
# ═══════════════════════════════════════════════════════════════
# 5. Nginx – konfiguracja tymczasowa (HTTP only, dla certbota)
# ═══════════════════════════════════════════════════════════════
banner "5/7 – Nginx (konfiguracja tymczasowa HTTP)"
NGINX_CONF="/etc/nginx/sites-available/pagan-web"
cat > "$NGINX_CONF" << 'NGINXHTTP'
# ═══════════════════════════════════════════════════════════════
# PaganOS Web v2 – Tymczasowy HTTP (do czasu uzyskania certyfikatu)
# ═══════════════════════════════════════════════════════════════
upstream pagan_web {
server 127.0.0.1:8000 fail_timeout=0;
}
server {
listen 80;
server_name _;
# Let's Encrypt challenge
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location /repo/download/ {
alias /var/www/repo.paganlinux.eu/;
expires 30d;
}
location /static/ {
alias /opt/pagan-web-v2/static/;
expires 7d;
}
location /build/api/stream {
proxy_pass http://pagan_web;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 3600s;
chunked_transfer_encoding on;
}
location / {
proxy_pass http://pagan_web;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
NGINXHTTP
ln -sf "$NGINX_CONF" /etc/nginx/sites-enabled/pagan-web 2>/dev/null || true
rm -f /etc/nginx/sites-enabled/default 2>/dev/null || true
nginx -t && systemctl restart nginx 2>/dev/null || nginx -s reload 2>/dev/null || warn "nginx – sprawdź konfigurację"
ok "Nginx HTTP – uruchomiony"
# ═══════════════════════════════════════════════════════════════
# 6. SSL – Let's Encrypt (Certbot)
# ═══════════════════════════════════════════════════════════════
banner "6/7 – SSL / Let's Encrypt"
CERT_OK=false
if [[ "$SETUP_SSL" == "yes" ]]; then
if [[ -f "/etc/letsencrypt/live/${DOMAIN}/fullchain.pem" ]]; then
ok "Certyfikat SSL już istnieje dla $DOMAIN"
CERT_OK=true
else
mkdir -p /var/www/certbot
sleep 2
echo -e " ${Y}▶${N} Pobieranie certyfikatu SSL..."
# Najpierw spróbuj certonly (bez ingerencji w nginx config)
certbot certonly --webroot \
--non-interactive --agree-tos \
-m "$EMAIL" \
-w /var/www/certbot \
-d "${DOMAIN}" \
-d "www.${DOMAIN}" \
-d "git.${DOMAIN}" \
-d "repo.${DOMAIN}" \
-d "build.${DOMAIN}" \
-d "docs.${DOMAIN}" \
2>&1 | sed 's/^/ │ /' || {
warn "certonly nie zadziałał, próbuję --nginx..."
certbot --nginx \
--non-interactive --agree-tos \
-m "$EMAIL" \
-d "${DOMAIN}" \
-d "www.${DOMAIN}" \
-d "git.${DOMAIN}" \
-d "repo.${DOMAIN}" \
-d "build.${DOMAIN}" \
-d "docs.${DOMAIN}" \
2>&1 | sed 's/^/ │ /' || true
}
if [[ -f "/etc/letsencrypt/live/${DOMAIN}/fullchain.pem" ]]; then
ok "Certyfikat SSL pobrany!"
CERT_OK=true
# Cron do auto-odnawiania
cat > /etc/cron.daily/pagan-cert-renew << 'CRONEOF'
#!/bin/bash
certbot renew --quiet --webroot -w /var/www/certbot
systemctl reload nginx
CRONEOF
chmod +x /etc/cron.daily/pagan-cert-renew
ok "Auto-renew SSL dodany (cron.daily)"
else
warn "Certbot nie mógł pobrać certyfikatu."
warn "Sprawdź DNS (wszystkie subdomeny muszą wskazywać na ten VPS) i port 80."
warn "Potem uruchom: certbot certonly --webroot -w /var/www/certbot -d paganlinux.eu"
fi
fi
else
warn "SSL pominięte (--no-ssl)"
fi
# ═══════════════════════════════════════════════════════════════
# 5b. Nginx – pełna konfiguracja HTTPS (po uzyskaniu certyfikatu)
# ═══════════════════════════════════════════════════════════════
banner "5b – Nginx (konfiguracja HTTPS)"
if [[ "$CERT_OK" == "true" ]]; then
cat > "$NGINX_CONF" << NGINXHTTPS
# ═══════════════════════════════════════════════════════════════
# PaganOS Web v2 – Pełna konfiguracja HTTPS
# Auto-generated: $(date)
# ═══════════════════════════════════════════════════════════════
upstream pagan_web {
server 127.0.0.1:8000 fail_timeout=0;
}
# ── HTTP → HTTPS redirect ──
server {
listen 80;
server_name ${DOMAIN} www.${DOMAIN}
git.${DOMAIN} repo.${DOMAIN}
build.${DOMAIN} docs.${DOMAIN};
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://\$host\$request_uri;
}
}
# ── HTTPS: Główna + www ──
server {
listen 443 ssl;
http2 on;
server_name ${DOMAIN} www.${DOMAIN};
ssl_certificate /etc/letsencrypt/live/${DOMAIN}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${DOMAIN}/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers off;
client_max_body_size 500m;
location /download/ {
alias /var/www/repo.paganlinux.eu/;
autoindex on;
autoindex_format html;
expires 30d;
add_header Cache-Control "public, immutable";
}
location /sources/ {
alias /var/www/repo.paganlinux.eu/sources/;
expires 7d;
}
location /static/ {
alias /opt/pagan-web-v2/static/;
expires 7d;
}
location /build/api/stream {
proxy_pass http://pagan_web;
proxy_http_version 1.1;
proxy_set_header Host \$host;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Real-IP \$remote_addr;
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 3600s;
chunked_transfer_encoding on;
}
location / {
proxy_pass http://pagan_web;
proxy_http_version 1.1;
proxy_set_header Host \$host;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
}
}
# ── HTTPS: Git ──
server {
listen 443 ssl;
http2 on;
server_name git.${DOMAIN};
ssl_certificate /etc/letsencrypt/live/${DOMAIN}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${DOMAIN}/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
client_max_body_size 500m;
location / {
proxy_pass http://pagan_web;
proxy_http_version 1.1;
proxy_set_header Host git.${DOMAIN};
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
}
}
# ── HTTPS: Repo ──
server {
listen 443 ssl;
http2 on;
server_name repo.${DOMAIN};
ssl_certificate /etc/letsencrypt/live/${DOMAIN}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${DOMAIN}/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
location /download/ {
alias /var/www/repo.paganlinux.eu/;
autoindex on;
autoindex_format html;
expires 30d;
add_header Cache-Control "public, immutable";
}
location / {
proxy_pass http://pagan_web;
proxy_http_version 1.1;
proxy_set_header Host repo.${DOMAIN};
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Real-IP \$remote_addr;
}
}
# ── HTTPS: Build ──
server {
listen 443 ssl;
http2 on;
server_name build.${DOMAIN};
ssl_certificate /etc/letsencrypt/live/${DOMAIN}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${DOMAIN}/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
location /api/stream {
proxy_pass http://pagan_web;
proxy_http_version 1.1;
proxy_set_header Host build.${DOMAIN};
proxy_set_header X-Forwarded-Proto https;
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 3600s;
chunked_transfer_encoding on;
}
location / {
proxy_pass http://pagan_web;
proxy_http_version 1.1;
proxy_set_header Host build.${DOMAIN};
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Real-IP \$remote_addr;
}
}
# ── HTTPS: Docs ──
server {
listen 443 ssl;
http2 on;
server_name docs.${DOMAIN};
ssl_certificate /etc/letsencrypt/live/${DOMAIN}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${DOMAIN}/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
location / {
proxy_pass http://pagan_web;
proxy_http_version 1.1;
proxy_set_header Host docs.${DOMAIN};
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Real-IP \$remote_addr;
}
}
NGINXHTTPS
nginx -t && systemctl reload nginx 2>/dev/null || nginx -s reload 2>/dev/null || warn "nginx reload – sprawdź"
ok "Nginx HTTPS – pełna konfiguracja z subdomenami"
else
# SSL się nie udał – zostawiamy HTTP
warn "SSL niedostępne – zostawiam konfigurację HTTP"
warn "Po uzyskaniu certyfikatu uruchom ponownie install.sh"
fi
# ═══════════════════════════════════════════════════════════════
# 7. Systemd + Firewall + Start
# ═══════════════════════════════════════════════════════════════
banner "7/7 – Usługi i finalizacja"
# ── Systemd service ──
cat > /etc/systemd/system/pagan-web.service << UNITEOF
[Unit]
Description=PaganOS Web v2 – Unified Platform
After=network.target nginx.service
Wants=network.target
[Service]
Type=simple
ExecStart=/usr/bin/python3 /opt/pagan-web-v2/app.py
WorkingDirectory=/opt/pagan-web-v2
Restart=always
RestartSec=5
User=root
EnvironmentFile=-/etc/pagan/build.conf
Environment=PYTHONUNBUFFERED=1
StandardOutput=journal
StandardError=journal
# Bezpieczeństwo
NoNewPrivileges=false
PrivateTmp=false
[Install]
WantedBy=multi-user.target
UNITEOF
systemctl daemon-reload
systemctl enable pagan-web 2>/dev/null || true
ok "systemd: pagan-web.service"
# ── Firewall ──
if [[ "$SETUP_FIREWALL" == "yes" ]] && command -v ufw &>/dev/null; then
ufw --force reset >/dev/null 2>&1 || true
ufw default deny incoming >/dev/null 2>&1 || true
ufw default allow outgoing >/dev/null 2>&1 || true
ufw allow 22/tcp comment "SSH" >/dev/null 2>&1 || true
ufw allow 80/tcp comment "HTTP" >/dev/null 2>&1 || true
ufw allow 443/tcp comment "HTTPS" >/dev/null 2>&1 || true
ufw --force enable >/dev/null 2>&1 || true
ok "Firewall (ufw): SSH + HTTP + HTTPS"
fi
# ── Cron – auto-build co 6h + codzienne czyszczenie cache ──
cat > /etc/cron.d/pagan-build << 'CRONBUILD'
# PaganOS – auto-build brakujących pakietów co 6 godzin
0 */6 * * * root /opt/pagan-web-v2/pagsync --once --missing >> /var/log/pagan-auto-build.log 2>&1
# Codzienne czyszczenie cache źródeł o 3:00
0 3 * * * root /opt/pagan-web-v2/pagsync --clean-cache >> /var/log/pagan-auto-build.log 2>&1
CRONBUILD
chmod 644 /etc/cron.d/pagan-build
ok "Cron: auto-build co 6h + clean-cache codziennie"
# ── Restart usług ──
nginx -t 2>/dev/null && systemctl restart nginx 2>/dev/null || nginx -s reload 2>/dev/null || warn "nginx restart – sprawdź konfigurację"
systemctl restart pagan-web 2>/dev/null || warn "pagan-web restart – sprawdź: systemctl status pagan-web"
# ═══════════════════════════════════════════════════════════════
# Podsumowanie
# ═══════════════════════════════════════════════════════════════
echo ""
echo -e "${G}╔══════════════════════════════════════════════════════════╗${N}"
echo -e "${G}║ ✅ PaganOS Web v2 – Instalacja zakończona! ║${N}"
echo -e "${G}╚══════════════════════════════════════════════════════════╝${N}"
echo ""
echo -e " ${B}🌐 Strony:${N}"
echo -e " Główna: https://${DOMAIN}"
echo -e " Git: https://git.${DOMAIN}"
echo -e " Repo: https://repo.${DOMAIN}"
echo -e " Build: https://build.${DOMAIN}"
echo -e " Docs: https://docs.${DOMAIN}"
echo ""
echo -e " ${B}🔧 Zarządzanie:${N}"
echo -e " Status: systemctl status pagan-web"
echo -e " Logi: journalctl -u pagan-web -f"
echo -e " Restart: systemctl restart pagan-web"
echo -e " Nginx: nginx -t && systemctl reload nginx"
echo ""
echo -e " ${B}📦 Budowanie pakietów:${N}"
echo -e " Wszystkie: pagsync --once"
echo -e " Force: pagsync --once --force"
echo -e " Jeden: pagsync --build nazwa"
echo -e " Z GPG: pagsync --once --sign"
echo ""
echo -e " ${B}🔑 Panel admin:${N}"
echo -e " Login: admin / paganadmin2024"
echo -e " Build: https://build.${DOMAIN}"
echo -e ""
if [[ -f "/etc/pagan/build.conf" ]]; then
echo -e " ${B}📋 Konfiguracja build:${N} /etc/pagan/build.conf"
cat /etc/pagan/build.conf | sed 's/^/ /'
fi
echo ""