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.
Tingkat terpilih: 301–600 siswa serentak. Cocok untuk sekolah menengah dengan ujian bergelombang per ruang.
| Siswa serentak | vCPU | RAM | Disk | PHP-FPM workers | Buffer pool DB |
|---|---|---|---|---|---|
| Sampai 100 | 2 | 2 GB | 25 GB SSD | 20 | 512 MB |
| 101 – 300 | 4 | 4 GB | 40 GB SSD | 40 | 1 GB |
| 301 – 600 | 4 | 8 GB | 60 GB NVMe | 80 | 3 GB |
| 601 – 1.000 | 8 | 16 GB | 100 GB NVMe | 140 | 8 GB |
| 1.001 – 2.000 | 8–16 | 32 GB | 200 GB NVMe | 220 | 16 GB |
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.
Alur Pemasangan
Seluruh proses terdiri dari delapan tahap. Setiap tahap dibahas berurutan di halaman ini.
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.iddan databasecbt_ujianperlu diganti sesuai milik Anda. - Siapkan juga berkas ZIP aplikasi dan kode lisensi dari penjual.
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:
ssh root@IP_VPSSetelah masuk, perbarui paket dan atur zona waktu serta nama server:
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:
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:
ssh-keygen -t ed25519
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:
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
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.
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.
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.
Memasang Nginx, PHP-FPM, dan MariaDB
Tumpukan yang ringan dan cepat untuk banyak koneksi serentak.
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):
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:
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.
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
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:
openssl rand -base64 24
Ganti GANTI_PASSWORD_KUAT dengan password tadi, lalu jalankan:
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;
SQLTabel 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:
scp ryuexam-cbt.zip deploy@IP_VPS:/tmp/Di server, ekstrak ke folder situs lalu atur kepemilikan dan izin berkas:
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:
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.zipFolder _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
sudo nano /var/www/ujian/config.php
Isi bagian $db_hosting, dan paksa mode hosting agar aplikasi selalu memakainya di server ini:
$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:
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:
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:
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:
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; }
}
EOFAktifkan situs, nonaktifkan situs bawaan Nginx, uji sintaks, lalu muat ulang:
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)
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d ujian.sekolah.sch.id --redirectIkuti pertanyaan interaktif (alamat email dan persetujuan ketentuan). Pembaruan sertifikat berjalan otomatis; ujilah dengan:
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.
Optimasi
Nilai pada kotak di bagian ini mengikuti tingkat yang Anda pilih di bagian Spesifikasi VPS. Ubah pilihan, dan nilainya ikut berubah.
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:
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:
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-fpmvalidate_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.
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
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:
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:
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):
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 nginxPerintah 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:
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:
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:
sudo journalctl --vacuum-size=200M
5. Pengaturan di dalam aplikasi
Beberapa pengaturan di panel admin ikut menentukan beban server. Buka Pengaturan lalu atur:
| Pengaturan | Saran untuk VPS | Alasan |
|---|---|---|
| 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 menit | Token yang berganti terlalu sering membuat siswa terlambat gagal login dan memicu lebih banyak percobaan. |
| Pencegahan Multi Login (Login Siswa) | Aktifkan | Mencegah satu akun dipakai di banyak perangkat sehingga beban dan kecurangan berkurang. |
| Jadwal ujian per ruang atau sesi | Bagi siswa dalam gelombang | Menurunkan 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.
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.
Siapkan alat di komputer Anda
Alatnya ada di folder
_loadtestpada paket aplikasi dan berjalan dari komputer Anda, bukan dari VPS. Klik dua kaliJalankan Uji Beban.bat. Panel terbuka di browser (http://127.0.0.1:8765/) dan jendela hitam harus tetap terbuka selama tes.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%.
Pantau server saat tes berjalan
Buka dua sesi SSH dan jalankan perintah di bawah. Perhatikan CPU, RAM, dan jumlah worker PHP-FPM.
Baca hasilnya
Setelah selesai, data uji dihapus otomatis (kecuali dicentang Jangan hapus). Bila tes terputus, klik Bersihkan Data Uji.
sudo apt install -y htop sysstat htop
watch -n 2 'curl -s http://127.0.0.1/fpm-status | head -14'
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
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 terlihat | Artinya | Tindakan |
|---|---|---|
max active processes sama dengan max_children dan max children reached bertambah | Worker 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 turun | Puncak login dan pembuatan sesi. Normal bila singkat. | Bagi siswa dalam gelombang, atau tambah vCPU bila antreannya lama. |
| RAM habis dan swap terpakai banyak | Total memori terlalu kecil untuk worker dan database. | Turunkan pm.max_children atau buffer pool, atau tambah RAM. |
Max_used_connections mendekati max_connections | Database hampir kehabisan koneksi. | Naikkan max_connections, dan pastikan nilainya lebih besar dari pm.max_children. |
| Banyak baris di log lambat | Ada 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 Nginx | PHP-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.
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:
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/ujianSalin 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:
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
df -h / free -h systemctl --no-pager --failed uptime
Memperbarui aplikasi
Cadangkan lebih dulu
Jalankan
sudo /usr/local/bin/backup-ujian.sh.Unggah paket pembaruan
Kirim ZIP ke
/tmpdenganscpseperti sebelumnya.Timpa tanpa menyentuh data
Perintah di bawah menyalin berkas baru, namun mengecualikan
config.php, folderdata, dan_backup_questions. Sesuaikan jalur folder hasil ekstrak.
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.
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
htopdan 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
Masalah Umum di VPS
| Gejala | Penyebab & solusi |
|---|---|
| 502 Bad Gateway | PHP-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 biasa | Izin berkas salah. Jalankan ulang perintah chown dan chmod di bagian Memasang Aplikasi. |
| Halaman PHP terunduh sebagai berkas | Blok 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 gagal | Naikkan 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 ujian | Puncak login. Mulai siswa bergelombang per ruang, dan cek CPU serta max children reached. |
| Disk penuh | Periksa df -h dan du -sh /var/backups/* /var/log/*. Perkecil masa simpan cadangan atau pindahkan keluar server. |
| Sertifikat HTTPS kedaluwarsa | Jalankan sudo certbot renew dan pastikan DNS serta port 80 masih terbuka. |
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.