T ToutadminBelgeler

Node sürümünü kurmak

Node sürümü sürekli bir servis olarak çalışır: tek bir süreç, diskte bir SQLite veritabanı, başka kurulacak bir şey yok — dış veritabanı yok, önbellek yok, kuyruk yok. Bu kılavuz boş bir dizinden üretimdeki kuruluma kadar gider; çoğu kılavuzun atladığı şeyler de içinde: sistem servisi, ters vekil sunucu, TLS, yedekler ve güncelleme.

Gerekenler#

ÖğeSürümNeden
Node.js22 ya da daha yenisiÜrün, gömülü test koşucusuna ve yeni arayüzlere dayanır.
Bir C derleyicisibuild-essentialbetter-sqlite3 kurulum sırasında derlenir; platformunuz için hazır ikili yoksa.
Yerel bir diskSQLite ve yüklenen dosyalar. Asla ağ paylaşımı: aşağıya bakın.

Tek çekirdekli ve 512 MB bellekli bir makine birkaç düzine kişiye yeter. Önemli olan güç değil, disktir: yerel olmalı ve yedeklenmelidir.

1. Almak ve kurmak#

git clone <deponuz> /var/www/toutadmin
cd /var/www/toutadmin
npm ci --omit=dev

npm install değil npm ci: kilit dosyasının anlattığını birebir kurar ve onu hiç yeniden yazmaz. Bir sunucuda kayan bir sürüm, kimsenin anlayamadığı bir arızadır.

Derleme başarısız olursa

C derleyen tek bağımlılık better-sqlite3'tür. sudo apt install -y build-essential python3 neredeyse bütün durumları çözer.

2. Yapılandırmak#

cp .env.example .env

Her şey ortam değişkenleriyle ayarlanır — .env'den okunur ya da servis yöneticiniz tarafından konur. Hiçbiri zorunlu değildir: .env olmadan kurulum 3000 portunda açılır ve sizi sihirbaza yollar.

DeğişkenVarsayılanNe yapar
PORT3000Dinlenen port.
NODE_ENVÜretimde production: sıkı çerezler, ayrıntılı iz yok.
SESSION_SECRETüretilirOturumları mühürler. Boş bırakılırsa data/session.key içinde üretilir.
INSTALL_TOKENSihirbazın kurulumdan önce istediği belirteç. Dışa açık sunucuda önerilir.
TRUST_PROXYGüvenilir bir vekil sunucunun ardında 1 — ve yalnızca orada.
DB_PATHdata/app.sqliteVeritabanı.
UPLOAD_DIR, CV_DIR, VAULT_DIR, SIGN_DIR, DOCS_DIR, BACKUP_DIRdata/ altındaDosya klasörleri: fotoğraflar, özgeçmişler, kasa, imza klasörü, gelen belgeler, arşivler.
LOGIN_RATE_LIMIT10Adres başına çeyrek saatte oturum açma denemesi.
GLOBAL_RATE_LIMIT300Adres başına dakikada istek.
API_RATE_LIMITBelirteç başına dakikada API çağrısı.
SESSION_IDLE_MINUTES60Oturumun düştüğü işlemsizlik süresi.
SESSION_MAX_HOURS12Hiçbir etkinliğin uzatmadığı mutlak süre.
ADMIN_EMAIL, ADMIN_PASSWORDArayüzsüz kurulum: yöneticiyi açılışta oluşturur.
Oturum sırrı

SESSION_SECRET'i değiştirmek herkesi bir anda dışarı atar. Bir kez koyun, rastgele üretin (node -e "console.log(require('crypto').randomBytes(32).toString('hex'))") ve geri kalanla birlikte yedekleyin. Asla bir git deposunda bırakmayın.

Kurulum belirteci koymak#

İlk açılışla sihirbaza uğramanız arasında kurulum onu bulanın olur: ilk gelen yönetim hesabını oluşturur. Bu yüzden portu açmadan önce INSTALL_TOKEN koyun:

node -e "console.log(require('crypto').randomBytes(16).toString('hex'))"
# sonra .env içine:
INSTALL_TOKEN=c3f1…

Sihirbaz onu sabit sürede karşılaştırır — sıradan bir karşılaştırma belirteci karakter karakter tahmin ettirirdi — ve her reddi günlüğe yazar. Kurulum tamamlandıktan sonra sihirbaz kendiliğinden kapanır.

Arayüzsüz kurmak#

Otomatik bir dağıtım için ADMIN_EMAIL ve ADMIN_PASSWORD, sihirbaza uğramadan, açılışta yöneticiyi oluşturur. Sonra onları kaldırın: bir servisin ortamındaki parolayı, o servisi okuyan herkes okur.

3. İzinler ve verilerin yeri#

sudo useradd --system --home /var/www/toutadmin --shell /usr/sbin/nologin toutadmin
sudo chown -R toutadmin:toutadmin /var/www/toutadmin/data
sudo chmod 750 /var/www/toutadmin/data
sudo chmod 640 /var/www/toutadmin/.env

Kod salt okunur kalabilir; yazılabilir olması gereken yalnızca data/'dır. SQLite komşu dosyalar yazar (-wal, -shm): önemli olan klasördür, yalnızca veritabanı değil.

Asla ağ paylaşımı üzerinde

NFS ve SMB, dosya kilitleme konusunda yalan söyler. SQLite iki eşzamanlı yazıyı engellemek için bu kilitlemeye güvenir: bir paylaşımda veritabanı uyarı vermeden bozulur. Her zaman yerel disk — ve başka yere giden yedektir, veritabanı değil.

4. Servis#

Elle başlatılan ürün, terminali kapattığınızda durur. Onu systemd'ye bırakın:

# /etc/systemd/system/toutadmin.service
[Unit]
Description=Toutadmin
After=network.target

[Service]
Type=simple
User=toutadmin
WorkingDirectory=/var/www/toutadmin
EnvironmentFile=/var/www/toutadmin/.env
ExecStart=/usr/bin/node src/server.js
Restart=always
RestartSec=5

# Servisin yalnızca data/ içine yazması gerekir.
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/www/toutadmin/data

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now toutadmin
sudo systemctl status toutadmin
journalctl -u toutadmin -f

Sertleştirmeye ilişkin beş satır süs değildir: ProtectSystem=strict bütün dosya sistemini yazılamaz kılar, ReadWritePaths ise yazılabilir olması gereken tek klasörü yeniden açar. Keyfî yazma açığı o zaman yalnızca data/'ya ulaşır.

5. Ters vekil sunucu#

3000 portunu asla doğrudan internete açmayın: TLS yapmaz ve bunu öğrenmesi için bir neden yoktur.

server {
    listen 443 ssl http2;
    server_name intranet.ornek.com.tr;

    ssl_certificate     /etc/letsencrypt/live/intranet.ornek.com.tr/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/intranet.ornek.com.tr/privkey.pem;

    client_max_body_size 20M;          # kasaya yüklemeler, gelen belgeler

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Host              $host;
        proxy_set_header X-Real-IP         $remote_addr;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

server {
    listen 80;
    server_name intranet.ornek.com.tr;
    return 301 https://$host$request_uri;
}

Ayrıca servisi yalnızca geri döngü arayüzünde dinletin ki 3000 portuna yalnızca vekil sunucu ulaşabilsin.

TLS#

sudo certbot --nginx -d intranet.ornek.com.tr

Ürün, bağlantı şifreli olur olmaz Strict-Transport-Security başlığını koyar ve asla açık metinde koymaz: şifresiz bir sayfadan duyurulsa okunmazdı, üstelik yerel bir denemeyi altı ay boyunca https içine hapsederdi.

TRUST_PROXY vekil sunucuyla gider — ve yalnızca onunla

Bu değişken, sunucunun bir başlıkta duyurulan köken adresine inanmasını sağlar. Nginx'in ardında gereken budur — yoksa bütün istekler 127.0.0.1'den geliyormuş gibi görünür ve adres başına sınırlar hiçbir şeyi korumaz. Önde vekil sunucu yoksa tersi olur: herkes istediği adresi duyurur ve sınırları aşar.

6. Sihirbaz#

Alan adınızı açın. Hiçbir hesap yokken bütün adresler /installation'a yönlenir. Beş adım:

  1. Kurulumun dili, 16 dil arasından.
  2. Önkoşullar, denetlenip gösterilir.
  3. Şirket: her yerde görünen ad.
  4. Serbest çalışan olmayan her yeni personele verilen yıllık izin.
  5. Yönetim hesabı: adres ve en az on iki karakterlik bir parola.

Bir hesap oluşur oluşmaz /installation giriş sayfasına yönlendirir: sihirbaz kendiliğinden kapanmıştır, elle silinecek hiçbir dosya yoktur.

7. Dönemsel süpürme#

PHP sürümünden farklı olarak zamanlanacak bir şey yoktur: sunucu kendi zamanlayıcısını taşır; saat başı uyanır ve sekiz iş görür.

Süpürme ne yaparGüvence
Sözleşmesi biten hesapları kapatırGirişte ve panonun açılışında da denetlenir
Vadesi gelen aboneliklerin faturalarını keserBir benzersiz dizin iki kez faturalamayı önler
Vadeleri bildirime çevirirYinelemeyi eleyen bir anahtar: bir vade bir kez uyarır
Okunmuş bildirimleri ve denetim günlüğünü temizlerSeçilen saklama süresine göre
Muhasebe posta kutusunu toplar (IMAP)Toplama yapılandırılmışsa
Web kancası kuyruğunu, yeniden denemeleriyle birlikte boşaltırBeş deneme, sonra vazgeçiş
Otomatik yedeği alır ve dışarı gönderirAralık dolduğunda

Her işlem eşgüçlüdür: yinelenen bir süpürme iki kez faturalamaz, iki kez bildirmez. Servisi istediğiniz anda düşünmeden yeniden başlatabilmenizi sağlayan da budur.

8. Her şeyin yürüdüğünü doğrulamak#

# testler (veritabanınıza yazmazlar)
npm test

# dolaşmak için bir gösterim kurulumu
node scripts/seed-demo.js

Sonra arayüzde: bir üye oluşturun, onunla girin, bir ek yükleyin, elle bir yedek alın ve Yedekler ekranından doğrulayın. Bu dört hareket veritabanına, dosyalara, yetkilere ve arşive dokunur.

9. Güncellemek#

# 1. önce bir yedek, her zaman — Yedekler ekranından

# 2. kod
cd /var/www/toutadmin
git pull
npm ci --omit=dev

# 3. yeniden başlatın; veritabanı açılışta kendini günceller
sudo systemctl restart toutadmin
journalctl -u toutadmin -n 30 --no-pager

Şema eşgüçlü göçlerle ilerler: güncellemeyi yeniden oynatmak hiçbir şeyi bozmaz. data/ ile .env'e hiç dokunulmaz.

Geri dönmek#

Kodu önceki sürüme alın ve yeniden başlatın. Göçler sütun silmez: göç etmiş bir veritabanı, sürüm günlüğü açıkça aksini söylemedikçe önceki sürümce okunabilir kalır. Kuşku duyarsanız 1. adımda aldığınız arşivi geri yükleyin.

10. Gerçekten yedeklemek#

tar.gz arşivi veritabanını ve beş dosya klasörünü taşır. Veritabanı, yazma sırasında bile tutarlı bir kopya üreten SQLite'ın çevrimiçi yedeğiyle kopyalanır — PHP sürümü aynı sonuca VACUUM INTO ile ulaşır. Her dosya kendi SHA-256 özetini taşır ve bu özet geri yüklemede doğrulanır.

Koruduğu sunucuda kalan bir arşiv hiçbir şeyi korumaz: Yedekler ekranından uzak bir hedef (FTPS ya da Google Drive) ayarlayın ve dışarı göndermenin başarısız olduğunu öğrenmek için sauvegarde.echec olayına bir web kancası bağlayın. Ayrıntısı Yedekleme ve geri yükleme sayfasındadır.

Önce yerelde denemek#

npm install
cp .env.example .env
npm run dev        # her değişiklikte yeniden başlar

http://localhost:3000 adresini açın. Yerelde NODE_ENV'i boş bırakın: production kipinde çerezler «güvenli» olarak imlenir ve açık bir bağlantıda saklanmaz — giriş sayfasında dönüp durursunuz.

PHP sürümüne geçmek ya da ondan gelmek#

İki sürüm aynı şemayı — 142 tablo, 1311 sütun — ve aynı parola biçimini paylaşır. Birini durdurun, app.sqlite dosyasını ve dosya klasörlerini kopyalayın, ötekini başlatın: dönüştürme yoktur. Bakınız İki sürüm.

Toutadmin belgeleri — 2026-09-13 tarihinde derlendi. Yazılımdan bağımsız, kendi başına bir site.