Instalasi & Optimasi di VPS (Manual)

Panduan dari memilih spesifikasi server berdasarkan jumlah siswa, memasang RyuExam CBT di VPS Ubuntu dengan Nginx, PHP-FPM, dan MariaDB, sampai optimasi, uji beban, dan cadangan. Semua perintah terminal bisa disalin dengan satu klik.

01

Menentukan Spesifikasi VPS

Pilih tingkat berdasarkan jumlah siswa yang mengerjakan ujian bersamaan, bukan jumlah seluruh siswa. Pilihan Anda juga mengatur nilai pada semua kotak perintah di halaman ini.

vCPU4
RAM8 GB
Penyimpanan60 GB NVMe
Transfer / bulan3 TB
Jaringan1 Gbps

Tingkat terpilih: 301–600 siswa serentak. Cocok untuk sekolah menengah dengan ujian bergelombang per ruang.

Siswa serentakvCPURAMDiskPHP-FPM workersBuffer pool DB
Sampai 10022 GB25 GB SSD20512 MB
101 – 30044 GB40 GB SSD401 GB
301 – 60048 GB60 GB NVMe803 GB
601 – 1.000816 GB100 GB NVMe1408 GB
1.001 – 2.0008–1632 GB200 GB NVMe22016 GB
Ini perkiraan, bukan jaminan

Angka di atas adalah titik awal yang konservatif, dihitung dari pola permintaan aplikasi (penjelasan di bawah), bukan hasil pengukuran di server tertentu. Selalu buktikan dengan uji beban sebelum hari ujian, lalu sesuaikan.

Dari mana angka ini berasal

Beban aplikasi ujian tidak merata. Ada tiga fase dengan kebutuhan berbeda:

Awal ujian (puncak CPU dan DB)

  • Siswa login dan memulai ujian hampir bersamaan, setiap siswa memicu beberapa kueri
  • Verifikasi password, berat di CPU bila password tersimpan sebagai hash
  • Soal dimuat, dan gambar soal diambil sekali per perangkat lalu disimpan browser

Saat mengerjakan (ringan)

  • Jawaban disinkronkan berkala, bawaan tiap 60 detik dengan jeda acak agar tersebar
  • Pemantauan pengawas tiap 10 detik, hanya dari sesi aktif
  • Satu siswa sekitar 1–2 permintaan per menit

Akhir ujian (puncak tulis DB)

  • Siswa mengumpulkan hampir bersamaan
  • Nilai dihitung dan disimpan per siswa secara atomik
  • Disk cepat dan buffer pool yang cukup sangat membantu
  • CPU menentukan seberapa cepat gelombang login di awal ujian terlayani. Bila ratusan siswa masuk dalam hitungan detik, tambah vCPU, atau bagi siswa per ruang agar mulai bergelombang.
  • RAM dibagi untuk PHP-FPM (sekitar 40–60 MB per worker), buffer pool database, dan sistem operasi. Karena itu RAM tidak boleh diirit.
  • Disk bukan soal kapasitas melainkan kecepatan. Pilih SSD atau NVMe. Gambar soal disimpan di database (dikompres ke WebP), sehingga ukuran database tumbuh seiring jumlah gambar, tetapi tetap kecil dibanding kapasitas disk yang disarankan.
  • Bandwidth server jarang jadi masalah, tetapi internet sekolah sering jadi penyempit. Ratusan siswa yang memuat soal bersamaan lewat satu jalur sekolah butuh sekitar 50–100 Mbps. Jika jalur sekolah kecil, pertimbangkan server di jaringan lokal (LAN).

Memilih penyedia VPS

  • Pilih virtualisasi KVM dengan sumber daya khusus (bukan oversold), dan lokasi pusat data di Indonesia atau Singapura agar latensi rendah.
  • Pilih sistem operasi Ubuntu 24.04 LTS. Panduan ini memakainya karena PHP 8.3 dan MariaDB sudah tersedia di repositori bawaan.
  • Pilih penyedia yang mengizinkan menaikkan paket per jam atau per hari. Anda bisa menaikkan spek hanya selama pekan ujian, lalu menurunkannya lagi.
  • Aktifkan snapshot atau backup bawaan penyedia sebagai lapisan cadangan tambahan.
02

Alur Pemasangan

Seluruh proses terdiri dari delapan tahap. Setiap tahap dibahas berurutan di halaman ini.

Cara memakai kotak perintah

Klik Salin pada kotak hitam, lalu tempel di terminal server. Teks berwarna kuning pada kotak adalah nilai yang mengikuti tingkat terpilih di atas, atau data yang wajib Anda ganti (contoh ujian.sekolah.sch.id). Perintah diawali sudo dijalankan sebagai user biasa yang punya hak sudo.

  • Semua perintah diuji alurnya untuk Ubuntu 24.04 LTS. Di Ubuntu 22.04, PHP 8.3 memerlukan repositori tambahan (PPA) sehingga nama paket dan jalur berkas berbeda.
  • Contoh domain ujian.sekolah.sch.id dan database cbt_ujian perlu diganti sesuai milik Anda.
  • Siapkan juga berkas ZIP aplikasi dan kode lisensi dari penjual.
03

Menyiapkan Server

Masuk ke VPS, perbarui sistem, buat user khusus, dan amankan akses sebelum memasang apa pun.

1. Masuk dan perbarui sistem

Dari komputer Anda (Windows PowerShell, macOS, atau Linux), masuk sebagai root memakai IP dari penyedia VPS:

Komputer Anda
ssh root@IP_VPS

Setelah masuk, perbarui paket dan atur zona waktu serta nama server:

Server (SSH)
apt update && apt upgrade -y
timedatectl set-timezone Asia/Jakarta
hostnamectl set-hostname server-ujian

2. Buat user khusus dan pakai kunci SSH

Jangan bekerja sebagai root. Buat user deploy dengan hak sudo:

Server (SSH)
adduser deploy
usermod -aG sudo deploy

Di komputer Anda, buat kunci SSH bila belum ada, lalu kirim kunci publiknya ke server. Perintah kedua untuk Windows PowerShell:

Komputer Anda (sekali saja)
ssh-keygen -t ed25519
Komputer Anda · Windows PowerShell
type $env:USERPROFILE\.ssh\id_ed25519.pub | ssh deploy@IP_VPS "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys"

Pada macOS atau Linux, cukup ssh-copy-id deploy@IP_VPS. Uji dulu bahwa ssh deploy@IP_VPS berhasil tanpa meminta password server.

3. Perketat SSH

Setelah login dengan kunci berhasil, matikan login root dan login dengan password:

Server (sebagai deploy)
sudo tee /etc/ssh/sshd_config.d/99-hardening.conf >/dev/null <<'EOF'
PermitRootLogin no
PasswordAuthentication no
EOF
sudo sshd -t && sudo systemctl reload ssh
Jangan tutup sesi lama dulu

Biarkan satu sesi SSH tetap terbuka, lalu buka sesi baru untuk memastikan Anda masih bisa masuk sebagai deploy dengan kunci. Bila gagal, perbaiki dari sesi yang masih terbuka. Jika tidak, Anda bisa terkunci dari server.

4. Firewall dan perlindungan brute force

Izinkan hanya SSH, HTTP, dan HTTPS. Izinkan SSH sebelum mengaktifkan firewall.

Server (sebagai deploy)
sudo apt install -y ufw fail2ban
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw --force enable
sudo systemctl enable --now fail2ban
sudo ufw status verbose

Port database (3306) sengaja tidak dibuka. MariaDB hanya melayani koneksi dari server itu sendiri.

Tambahan swap untuk RAM kecil

Pada tingkat 2 GB dan 4 GB, tambahkan swap 2 GB sebagai pengaman agar proses tidak dimatikan sistem saat memori penuh. Perintah ada di bagian Optimasi Sistem Operasi.

04

Memasang Nginx, PHP-FPM, dan MariaDB

Tumpukan yang ringan dan cepat untuk banyak koneksi serentak.

Server (sebagai deploy)
sudo apt install -y nginx mariadb-server unzip rsync curl \
  php8.3-fpm php8.3-cli php8.3-mysql php8.3-mbstring php8.3-zip php8.3-gd php8.3-curl php8.3-xml php8.3-intl

Periksa bahwa ekstensi yang dibutuhkan aplikasi aktif (sodium dipakai untuk verifikasi lisensi):

Server
php -v
php -m | grep -E "pdo_mysql|mysqli|sodium|zip|mbstring|gd|curl|openssl"

Delapan nama ekstensi harus tampil. Lalu pastikan layanan berjalan dan menyala otomatis saat server hidup:

Server
sudo systemctl enable --now nginx mariadb php8.3-fpm
systemctl is-active nginx mariadb php8.3-fpm

Amankan MariaDB. Jawab pertanyaan sesuai saran di bawah kotak.

Server
sudo mariadb-secure-installation
  • Switch to unix_socket authentication: N (sudah bawaan)  ·  Change root password: N bila memakai socket
  • Remove anonymous users: Y  ·  Disallow root login remotely: Y
  • Remove test database: Y  ·  Reload privilege tables: Y
05

Memasang Aplikasi

Buat database, unggah aplikasi, isi koneksi, lalu pasang situs di Nginx dengan HTTPS.

1. Buat database dan user

Buat password yang kuat dan catat hasilnya:

Server
openssl rand -base64 24

Ganti GANTI_PASSWORD_KUAT dengan password tadi, lalu jalankan:

Server
sudo mariadb <<'SQL'
CREATE DATABASE cbt_ujian CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'cbt_user'@'localhost' IDENTIFIED BY 'GANTI_PASSWORD_KUAT';
GRANT ALL PRIVILEGES ON cbt_ujian.* TO 'cbt_user'@'localhost';
FLUSH PRIVILEGES;
SQL

Tabel dibuat otomatis saat aplikasi pertama kali dibuka. Jika paket Anda menyertakan berkas .sql, impor dengan sudo mariadb cbt_ujian < berkas.sql.

2. Unggah dan ekstrak aplikasi

Dari komputer Anda, kirim berkas ZIP ke server:

Komputer Anda
scp ryuexam-cbt.zip deploy@IP_VPS:/tmp/

Di server, ekstrak ke folder situs lalu atur kepemilikan dan izin berkas:

Server
sudo mkdir -p /var/www/ujian
sudo unzip -q /tmp/ryuexam-cbt.zip -d /var/www/ujian
ls -la /var/www/ujian | head -20

Pastikan index.php, admin.php, dan config.php terlihat langsung di /var/www/ujian. Jika terbentuk satu subfolder tambahan, pindahkan isinya ke atas lebih dulu. Lalu:

Server
sudo chown -R www-data:www-data /var/www/ujian
sudo find /var/www/ujian -type d -exec chmod 755 {} \;
sudo find /var/www/ujian -type f -exec chmod 644 {} \;
rm /tmp/ryuexam-cbt.zip
Jangan unggah folder uji beban

Folder _loadtest adalah alat uji beban yang dijalankan dari komputer Anda, bukan dari server. Jika ikut terunggah, hapus dengan sudo rm -rf /var/www/ujian/_loadtest (periksa dulu bahwa jalurnya benar).

3. Isi koneksi database di config.php

Server
sudo nano /var/www/ujian/config.php

Isi bagian $db_hosting, dan paksa mode hosting agar aplikasi selalu memakainya di server ini:

config.php
$environment_mode = 'hosting';

$db_hosting = [
    'host' => 'localhost',
    'port' => '3306',
    'name' => 'cbt_ujian',
    'user' => 'cbt_user',
    'pass' => 'GANTI_PASSWORD_KUAT',
];

Simpan dengan Ctrl+O, Enter, lalu keluar dengan Ctrl+X. Batasi akses berkas ini:

Server
sudo chmod 640 /var/www/ujian/config.php
sudo chown www-data:www-data /var/www/ujian/config.php

4. Pasang situs di Nginx

Arahkan dulu DNS domain/subdomain ke IP VPS (rekaman A) dan tunggu sampai aktif. Aplikasi memakai .htaccess khusus Apache untuk melindungi berkas, sedangkan Nginx tidak membaca .htaccess. Karena itu konfigurasi di bawah menerjemahkan aturan yang sama: folder internal diblokir, berkas sensitif ditolak, header keamanan dipasang, gambar soal di-cache lama, dan skrip PHP tidak di-cache.

Pertama, berkas potongan untuk header keamanan:

Server
sudo tee /etc/nginx/snippets/ryuexam-headers.conf >/dev/null <<'EOF'
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
EOF

Kedua, zona cache untuk gambar soal. Gambar disimpan di database dan disajikan lewat img.php; dengan cache ini, Nginx melayani gambar dari disk sehingga PHP dan database tidak dipanggil berulang untuk tiap siswa:

Server
sudo tee /etc/nginx/conf.d/ryuexam-cache.conf >/dev/null <<'EOF'
fastcgi_cache_path /var/cache/nginx/ryuexam levels=1:2 keys_zone=ryuimg:20m max_size=500m inactive=7d use_temp_path=off;
EOF

Ketiga, konfigurasi situs. Ganti ujian.sekolah.sch.id dengan domain Anda:

Server
sudo tee /etc/nginx/sites-available/ujian >/dev/null <<'EOF'
server {
    listen 80;
    listen [::]:80;
    server_name ujian.sekolah.sch.id;
    root /var/www/ujian;
    index index.php;
    server_tokens off;
    client_max_body_size 64M;

    include snippets/ryuexam-headers.conf;

    # 1. Folder internal tidak boleh dibuka dari browser
    location ~ ^/(views|_backup_questions|data|_loadtest)/ { return 403; }

    # 2. Berkas tersembunyi dan berkas sensitif
    location ~ /\.(?!well-known) { return 403; }
    location ~* \.(json|sql|docx?|log|md|txt|bak|old|env|sh|bat|ini|conf|ya?ml)$ { return 403; }
    location = /manifest.json { try_files $uri =404; }

    # 3. Gambar soal: isinya tidak pernah berubah, cache di Nginx dan browser
    location = /img.php {
        include snippets/ryuexam-headers.conf;
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
        fastcgi_hide_header Cache-Control;
        fastcgi_cache ryuimg;
        fastcgi_cache_key "$scheme$host$request_uri";
        fastcgi_cache_valid 200 30d;
        fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
        add_header Cache-Control "public, max-age=31536000, immutable";
    }

    # 4. Aset statis
    location ~* \.(css|js)$ {
        include snippets/ryuexam-headers.conf;
        expires 7d;
        access_log off;
    }
    location ~* \.(png|jpe?g|gif|webp|svg|ico|woff2?|ttf)$ {
        include snippets/ryuexam-headers.conf;
        expires 30d;
        access_log off;
    }

    # 5. Skrip PHP (API dan admin) tidak boleh di-cache
    location ~ \.php$ {
        include snippets/ryuexam-headers.conf;
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
        fastcgi_read_timeout 120;
        fastcgi_hide_header Cache-Control;
        add_header Cache-Control "private, no-cache, no-store, must-revalidate" always;
    }

    # Status PHP-FPM, hanya dari server ini (untuk pemantauan)
    location = /fpm-status {
        allow 127.0.0.1;
        deny all;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
    }

    location / { try_files $uri $uri/ =404; }
}
EOF

Aktifkan situs, nonaktifkan situs bawaan Nginx, uji sintaks, lalu muat ulang:

Server
sudo ln -sf /etc/nginx/sites-available/ujian /etc/nginx/sites-enabled/ujian
sudo rm -f /etc/nginx/sites-enabled/default
sudo nginx -t && sudo systemctl reload nginx

Pastikan tulisan syntax is ok muncul. Bagian /fpm-status baru bekerja setelah pool PHP-FPM di bagian Optimasi dibuat. Jangan khawatir bila sebelum itu halaman PHP belum tampil.

5. Pasang HTTPS (Let's Encrypt)

Server
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d ujian.sekolah.sch.id --redirect

Ikuti pertanyaan interaktif (alamat email dan persetujuan ketentuan). Pembaruan sertifikat berjalan otomatis; ujilah dengan:

Server
sudo certbot renew --dry-run

Setelah selesai dan bagian Optimasi dikerjakan, buka https://ujian.sekolah.sch.id/admin.php, masuk dengan akun admin dari paket, ganti password, lalu aktifkan lisensi lewat Memasukkan Lisensi.

06

Optimasi

Nilai pada kotak di bagian ini mengikuti tingkat yang Anda pilih di bagian Spesifikasi VPS. Ubah pilihan, dan nilainya ikut berubah.

Tingkat aktif:301–600 siswa serentakGanti

1. PHP-FPM dan OPcache

PHP-FPM mengatur berapa permintaan PHP yang dilayani bersamaan. Terlalu sedikit membuat siswa mengantre, terlalu banyak menghabiskan RAM. Rumus kasarnya: (RAM − RAM untuk database dan sistem) ÷ 50 MB. Gantikan pool bawaan dengan pool khusus aplikasi:

Server
sudo mv /etc/php/8.3/fpm/pool.d/www.conf /etc/php/8.3/fpm/pool.d/www.conf.disabled
sudo tee /etc/php/8.3/fpm/pool.d/ryuexam.conf >/dev/null <<'EOF'
[ryuexam]
user = www-data
group = www-data
listen = /run/php/php8.3-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.backlog = 4096

pm = dynamic
pm.max_children = 80
pm.start_servers = 20
pm.min_spare_servers = 10
pm.max_spare_servers = 30
pm.max_requests = 500
pm.status_path = /fpm-status

request_terminate_timeout = 120s
php_admin_value[error_log] = /var/log/php8.3-fpm-ryuexam.log
php_admin_flag[log_errors] = on
EOF

Lalu atur PHP dan OPcache. OPcache menyimpan kode PHP yang sudah dikompilasi sehingga permintaan berikutnya jauh lebih cepat:

Server
sudo tee /etc/php/8.3/fpm/conf.d/99-ryuexam.ini >/dev/null <<'EOF'
memory_limit = 256M
upload_max_filesize = 64M
post_max_size = 64M
max_execution_time = 120
date.timezone = Asia/Jakarta

opcache.enable = 1
opcache.memory_consumption = 256
opcache.interned_strings_buffer = 16
opcache.max_accelerated_files = 20000
opcache.validate_timestamps = 1
opcache.revalidate_freq = 60
EOF
sudo php-fpm8.3 -t && sudo systemctl restart php8.3-fpm

validate_timestamps dibiarkan aktif dengan jeda 60 detik agar pembaruan berkas aplikasi otomatis terbaca tanpa restart manual.

2. MariaDB

Parameter terpenting adalah innodb_buffer_pool_size, yaitu memori yang dipakai database untuk menyimpan data aktif. Nilainya sekitar 40–50% dari RAM bila server juga menjalankan PHP.

Server
sudo tee /etc/mysql/mariadb.conf.d/99-ryuexam.cnf >/dev/null <<'EOF'
[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
skip_name_resolve = 1
bind-address = 127.0.0.1

innodb_buffer_pool_size = 3G
innodb_log_file_size = 512M
innodb_flush_method = O_DIRECT
innodb_flush_log_at_trx_commit = 2

max_connections = 250
max_allowed_packet = 64M
thread_cache_size = 64
table_open_cache = 2000
tmp_table_size = 64M
max_heap_table_size = 64M

slow_query_log = 1
slow_query_log_file = /var/log/mysql/mariadb-slow.log
long_query_time = 1
EOF
sudo systemctl restart mariadb
Tentang innodb_flush_log_at_trx_commit = 2

Dengan nilai 2, database menulis log ke disk sekali per detik, bukan setiap transaksi. Hasilnya penulisan jauh lebih cepat saat ratusan siswa mengumpulkan jawaban bersamaan. Risikonya: bila server mati mendadak (listrik atau crash sistem), paling banyak sekitar 1 detik transaksi terakhir bisa hilang. Karena aplikasi menyinkronkan jawaban tiap 60 detik, risiko ini kecil. Jika Anda ingin keamanan data maksimum, ubah ke 1.

Periksa bahwa pengaturan terbaca:

Server
sudo mariadb -e "SHOW VARIABLES WHERE Variable_name IN ('innodb_buffer_pool_size','max_connections','innodb_flush_log_at_trx_commit');"

3. Nginx

Naikkan batas koneksi serentak dan aktifkan kompresi untuk data JSON, CSS, dan JavaScript:

Server
sudo tee /etc/nginx/conf.d/ryuexam-gzip.conf >/dev/null <<'EOF'
gzip_vary on;
gzip_comp_level 5;
gzip_min_length 1024;
gzip_types text/plain text/css text/xml application/json application/javascript text/javascript application/xml image/svg+xml;
EOF
grep -n "gzip on" /etc/nginx/nginx.conf

Baris terakhir harus menampilkan gzip on;. Bila tidak muncul, tambahkan gzip on; di blok http pada /etc/nginx/nginx.conf. Selanjutnya naikkan batas berkas terbuka dan koneksi per worker (jalankan satu kali saja):

Server
sudo sed -i 's/^\s*worker_connections.*/    worker_connections 8192;/' /etc/nginx/nginx.conf
sudo sed -i '/^worker_processes/a worker_rlimit_nofile 65535;' /etc/nginx/nginx.conf
sudo nginx -t && sudo systemctl reload nginx

Perintah kedua menambah satu baris di nginx.conf. Jika dijalankan dua kali, Nginx menolak karena baris ganda. Periksa dengan sudo nginx -t.

4. Sistem operasi

Naikkan batas antrean koneksi dan berkas terbuka, dan kurangi kecenderungan memakai swap:

Server
sudo tee /etc/sysctl.d/99-ryuexam.conf >/dev/null <<'EOF'
net.core.somaxconn = 4096
net.ipv4.tcp_max_syn_backlog = 4096
net.ipv4.ip_local_port_range = 10240 65535
net.ipv4.tcp_tw_reuse = 1
fs.file-max = 200000
vm.swappiness = 10
EOF
sudo sysctl --system >/dev/null

Pada tingkat 2 GB dan 4 GB, tambahkan swap 2 GB sebagai pengaman:

Server
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
free -h

Putar log agar disk tidak penuh. Ubuntu sudah memutar log Nginx dan MariaDB secara otomatis. Batasi ukuran log sistemd dengan:

Server
sudo journalctl --vacuum-size=200M

5. Pengaturan di dalam aplikasi

Beberapa pengaturan di panel admin ikut menentukan beban server. Buka Pengaturan lalu atur:

PengaturanSaran untuk VPSAlasan
Interval Sinkronisasi Jawaban (Umum)60 detik untuk sampai 300 siswa. 75–90 detik untuk 300 sampai 1.000. 90–120 detik untuk lebih dari 1.000.Makin jarang sinkronisasi, makin sedikit permintaan. Aplikasi menyebarkan waktunya secara acak. Batas yang diterima 30–600 detik.
Token Dinamis (Token Dinamis)Interval 30–60 menitToken yang berganti terlalu sering membuat siswa terlambat gagal login dan memicu lebih banyak percobaan.
Pencegahan Multi Login (Login Siswa)AktifkanMencegah satu akun dipakai di banyak perangkat sehingga beban dan kecurangan berkurang.
Jadwal ujian per ruang atau sesiBagi siswa dalam gelombangMenurunkan puncak login dan puncak pengumpulan jawaban. Efeknya sering lebih besar daripada menambah spek.

Untuk memantau secara langsung, buka menu Status Ujian. Halaman itu membaca hanya jadwal aktif dan data tidak diperbarui otomatis, sehingga aman dibuka beberapa pengawas sekaligus.

07

Uji Beban Sebelum Hari Ujian

Buktikan bahwa server sanggup menampung jumlah siswa Anda. Aplikasi menyertakan alat uji beban yang meniru siswa sungguhan: membuka halaman, login, memulai ujian, memuat soal, menjawab dan menyinkronkan, lalu mengumpulkan.

  1. Siapkan alat di komputer Anda

    Alatnya ada di folder _loadtest pada paket aplikasi dan berjalan dari komputer Anda, bukan dari VPS. Klik dua kali Jalankan Uji Beban.bat. Panel terbuka di browser (http://127.0.0.1:8765/) dan jendela hitam harus tetap terbuka selama tes.

  2. Isi data tes

    Masukkan URL aplikasi di VPS, username dan password admin, serta jumlah siswa virtual. Mulailah dari 50% target, lalu naik ke 100% dan 120%.

  3. Pantau server saat tes berjalan

    Buka dua sesi SSH dan jalankan perintah di bawah. Perhatikan CPU, RAM, dan jumlah worker PHP-FPM.

  4. Baca hasilnya

    Setelah selesai, data uji dihapus otomatis (kecuali dicentang Jangan hapus). Bila tes terputus, klik Bersihkan Data Uji.

Sesi SSH 1: CPU, RAM, antrean
sudo apt install -y htop sysstat
htop
Sesi SSH 2: status PHP-FPM tiap 2 detik
watch -n 2 'curl -s http://127.0.0.1/fpm-status | head -14'
Setelah tes: koneksi DB tertinggi dan log lambat
sudo mariadb -e "SHOW GLOBAL STATUS LIKE 'Max_used_connections'; SHOW GLOBAL STATUS LIKE 'Threads_connected';"
sudo tail -n 20 /var/log/mysql/mariadb-slow.log
sudo tail -n 20 /var/log/nginx/error.log
Aturan penting uji beban

Jalankan hanya saat tidak ada ujian sungguhan, karena alat ini mengimpor dan menghapus data siswa uji. Semua siswa virtual datang dari satu IP (komputer Anda), jadi matikan sementara pembatas laju atau WAF seperti Cloudflare. Hasil juga dipengaruhi koneksi internet komputer Anda.

Cara menafsirkan hasil

Yang terlihatArtinyaTindakan
max active processes sama dengan max_children dan max children reached bertambahWorker PHP habis, permintaan mengantre.Jika RAM masih longgar, naikkan pm.max_children. Jika RAM mepet, tambah RAM atau pakai tingkat yang lebih besar.
CPU 90–100% di awal tes lalu turunPuncak login dan pembuatan sesi. Normal bila singkat.Bagi siswa dalam gelombang, atau tambah vCPU bila antreannya lama.
RAM habis dan swap terpakai banyakTotal memori terlalu kecil untuk worker dan database.Turunkan pm.max_children atau buffer pool, atau tambah RAM.
Max_used_connections mendekati max_connectionsDatabase hampir kehabisan koneksi.Naikkan max_connections, dan pastikan nilainya lebih besar dari pm.max_children.
Banyak baris di log lambatAda kueri yang butuh lebih dari 1 detik.Periksa disk, buffer pool, dan jumlah data. Laporkan kueri yang lambat ke penjual aplikasi.
Galat 502/504 di error.log NginxPHP-FPM kewalahan atau timeout.Periksa log /var/log/php8.3-fpm-ryuexam.log dan nilai di atas.

Ulangi tes setelah setiap perubahan, satu perubahan dalam satu waktu, supaya jelas mana yang berpengaruh.

08

Backup, Pemantauan, dan Pembaruan

Backup otomatis harian

Skrip berikut mencadangkan database dan berkas penting setiap malam pukul 01.30, lalu menghapus cadangan yang lebih tua dari 14 hari:

Server
sudo tee /usr/local/bin/backup-ujian.sh >/dev/null <<'EOF'
#!/bin/bash
set -euo pipefail
DIR=/var/backups/ujian
STAMP=$(date +%F_%H%M)
mkdir -p "$DIR"
mariadb-dump --single-transaction --quick cbt_ujian | gzip > "$DIR/cbt_ujian_$STAMP.sql.gz"
tar -czf "$DIR/berkas_$STAMP.tar.gz" -C /var/www ujian/data ujian/_backup_questions ujian/config.php
find "$DIR" -type f -mtime +14 -delete
EOF
sudo chmod 750 /usr/local/bin/backup-ujian.sh
echo "30 1 * * * root /usr/local/bin/backup-ujian.sh" | sudo tee /etc/cron.d/backup-ujian
sudo /usr/local/bin/backup-ujian.sh && ls -lh /var/backups/ujian

Salin cadangan keluar dari server secara berkala, misalnya ke komputer Anda atau penyimpanan cloud, karena cadangan di server yang sama ikut hilang bila server rusak. Dari komputer Anda:

Komputer Anda
scp deploy@IP_VPS:/var/backups/ujian/*.gz .

Agar user deploy bisa membacanya, jalankan satu kali di server: sudo chmod 750 /var/backups/ujian && sudo chgrp deploy /var/backups/ujian. Selain itu, unduh juga cadangan dari menu Pengaturan › Database sebelum dan sesudah ujian.

Pemantauan harian

Server
df -h /
free -h
systemctl --no-pager --failed
uptime

Memperbarui aplikasi

  1. Cadangkan lebih dulu

    Jalankan sudo /usr/local/bin/backup-ujian.sh.

  2. Unggah paket pembaruan

    Kirim ZIP ke /tmp dengan scp seperti sebelumnya.

  3. Timpa tanpa menyentuh data

    Perintah di bawah menyalin berkas baru, namun mengecualikan config.php, folder data, dan _backup_questions. Sesuaikan jalur folder hasil ekstrak.

Server
mkdir -p /tmp/update
unzip -q /tmp/ryuexam-update.zip -d /tmp/update
sudo rsync -a --exclude 'config.php' --exclude 'data/' --exclude '_backup_questions/' --exclude '_loadtest/' /tmp/update/ /var/www/ujian/
sudo chown -R www-data:www-data /var/www/ujian
sudo systemctl reload php8.3-fpm

Buka situs sekali agar pembaruan tabel berjalan otomatis, lalu cek Log Pembaruan di panel admin untuk memastikan versinya benar.

09

Daftar Periksa Hari Ujian

H-7 sampai H-1

  • Uji beban pada 100% dan 120% target
  • Backup dan restore diuji sekali
  • Sertifikat HTTPS aktif dan lisensi aktif
  • Server naik ke spek ujian bila memakai paket per jam
  • Tunda pembaruan sistem sampai ujian selesai

Hari ujian

  • Cek ruang disk, RAM kosong, dan systemctl --failed
  • Jalankan backup sebelum mulai
  • Buka htop dan status FPM di sesi terpisah
  • Mulai siswa per ruang agar login bergelombang
  • Siapkan satu pengawas untuk membuka kunci siswa

Setelah ujian

  • Pastikan semua siswa sudah mengumpulkan
  • Unduh rekap nilai dan jawaban
  • Jalankan backup, salin keluar server
  • Turunkan spek VPS bila tidak dipakai lagi
  • Lihat Analisis Soal untuk evaluasi
10

Masalah Umum di VPS

GejalaPenyebab & solusi
502 Bad GatewayPHP-FPM mati atau jalur soket salah. Periksa systemctl status php8.3-fpm dan pastikan jalur /run/php/php8.3-fpm.sock sama di Nginx dan pool.
403 saat membuka halaman biasaIzin berkas salah. Jalankan ulang perintah chown dan chmod di bagian Memasang Aplikasi.
Halaman PHP terunduh sebagai berkasBlok location ~ \.php$ belum aktif. Jalankan sudo nginx -t dan muat ulang Nginx.
“Gagal Terhubung ke Database MySQL”Data di $db_hosting keliru, atau $environment_mode belum 'hosting'. Uji dengan sudo mariadb -u cbt_user -p cbt_ujian.
“Ekstensi PHP sodium tidak aktif”Pasang ulang php8.3-common (berisi sodium), lalu sudo systemctl restart php8.3-fpm.
Impor atau unggah berkas besar gagalNaikkan client_max_body_size di Nginx dan upload_max_filesize serta post_max_size di 99-ryuexam.ini, lalu muat ulang keduanya.
Lambat saat awal ujianPuncak login. Mulai siswa bergelombang per ruang, dan cek CPU serta max children reached.
Disk penuhPeriksa df -h dan du -sh /var/backups/* /var/log/*. Perkecil masa simpan cadangan atau pindahkan keluar server.
Sertifikat HTTPS kedaluwarsaJalankan sudo certbot renew dan pastikan DNS serta port 80 masih terbuka.
Perlu bantuan?

Untuk memasang atau menyetel VPS bersama tim kami, hubungi lewat WhatsApp dengan menyebutkan jumlah siswa dan penyedia VPS yang dipakai.

Ingin dipasangkan di VPS?

Kami bisa membantu instalasi, optimasi, dan uji beban sesuai jumlah siswa sekolah Anda.

Chat WhatsApp Dokumentasi