Upgrade SIMGOS: Panduan Naik ke 2.7.9 Tanpa Kehilangan Data dan Patch Lokal

Upgrade SIMGOS 2.6.11 ke 2.7.9 tanpa kehilangan data: backup, gladi resik, dan cutover aman

Bayangkan Anda harus merenovasi ruang IGD, tetapi rumah sakit tidak boleh tutup sehari pun. Pasien tetap datang, dokter tetap bekerja, dan semua rekam medis harus tetap utuh. Begitulah rasanya melakukan upgrade SIMGOS di rumah sakit yang berjalan 24 jam. Artikel ini membagikan alur nyata kami saat menaikkan SIMGOS sebuah RSUD dari versi 2.6.11 ke 2.7.9, sekaligus menaikkan PHP 7.4 ke 8.2. Hasilnya, layanan hanya berhenti sekitar 3,5 menit, tidak ada data yang hilang, dan semua patch lokal rumah sakit tetap berfungsi.

Panduan ini cocok untuk tim IT rumah sakit, vendor lokal, maupun admin server yang baru pertama kali memegang SIMGOS. Kami menulisnya bertahap, lengkap dengan perintah yang benar-benar kami jalankan, screenshot asli yang sudah tersensor, serta jebakan yang hampir merusak data.

Diagram jalur upgrade SIMGOS dari 2.6.11 langsung ke 2.7.9 melewati lima rilis antara
Server kami tertinggal 6 rilis. Semua rilis antara terlewati, tetapi patch database-nya tetap berjalan berurutan.

Kenapa Upgrade SIMGOS Tidak Bisa Asal dnf update

SIMGOS (SIMRS Generik Open Source dari Kemenkes) datang sebagai paket RPM bernama simgos. Sekilas, cukup menjalankan dnf update. Namun, paket ini membawa skrip instalasi yang melakukan jauh lebih banyak hal daripada menyalin file. Oleh karena itu, kita perlu tahu persis apa yang akan terjadi sebelum menekan Enter.

BagianYang paket kerjakanRisiko bagi rumah sakit
File aplikasiMenimpa semua file milik paket (tanpa file config)Patch lokal RS hilang tanpa peringatan
DatabaseMenjalankan ratusan file SQL patch secara berurutanProsedur cetak lokal tertimpa, data bisa terpotong
PHPBila masih 7.4, skrip menghapus PHP lalu mengunduh 8.2Server tanpa PHP bila unduhan gagal
Web serverMengganti php.conf dan hak akses folderTagihan, report, dan BPJS bisa error 503

Selain itu, rollback lewat dnf downgrade tidak membatalkan perubahan database. Dengan demikian, satu-satunya jalan pulang adalah backup yang sudah teruji.

Alur Upgrade SIMGOS yang Aman

Kami membagi pekerjaan menjadi dua fase. Fase persiapan berjalan saat SIMGOS tetap melayani pasien. Kemudian fase eksekusi berlangsung singkat di jam sepi, setelah semua uji lolos.

Diagram alur upgrade SIMGOS tujuh tahap dari bongkar paket sampai uji asap
Empat tahap pertama tanpa downtime. Downtime hanya terjadi di tahap 5 sampai 7.

Prinsipnya sederhana. Pertama, pelajari paket tanpa memasangnya. Kedua, amankan data. Ketiga, uji seluruh proses di salinan. Terakhir, jalankan di server asli dengan skrip yang berhenti sendiri bila ada yang tidak beres.

Langkah 1: Cek Versi dan Bongkar Paket Tanpa Memasang

Mula-mula, lihat versi yang terpasang dan versi yang tersedia di repositori. Perintah berikut menampilkan semua build paket simgos.

dnf list --showduplicates simgos
rpm -qi simgos | head -5
Daftar versi paket saat persiapan upgrade SIMGOS, terpasang 2.6.11 dan tersedia sampai 2.7.9
Screenshot asli sebelum upgrade. Garis kuning menandai versi yang terpasang.

Selanjutnya, unduh paket target ke folder kerja lalu bongkar isinya. Cara ini tidak mengubah apa pun di server, jadi Anda aman menjalankannya kapan saja.

mkdir -p /root/simgos-upg/rpm /root/simgos-upg/new
cd /root/simgos-upg/rpm && dnf download simgos-2.7.9-26101200
cd /root/simgos-upg/new && rpm2cpio ../rpm/simgos-2.7.9*.rpm | cpio -idm

# skrip yang akan berjalan saat install, dan file yang dianggap config
rpm -qp --scripts ../rpm/simgos-2.7.9*.rpm
rpm -qpc ../rpm/simgos-2.7.9*.rpm

Dari langkah ini kami menemukan tiga fakta penting. Paket tidak menandai satu file pun sebagai config. Skrip pascainstalasi memanggil install-rockylinux.sh, yang menjalankan patch database. Lalu, bila PHP masih 7.4, skrip yang sama menjalankan php_74_to_82.sh.

Langkah 2: Backup Database, Aplikasi, dan Dokumen

Backup adalah satu-satunya tiket pulang. Karena itu, kami mengambil backup lengkap dan menyimpannya di tiga tempat: server, folder backup terkunci, dan laptop IT.

B=/backup/simgos-pre-upgrade-$(date +%Y%m%d-%H%M); mkdir -p $B; chmod 700 /backup

# database: konsisten, lengkap dengan routine, trigger, event, posisi binlog
mysqldump --defaults-file=/root/.my-root.cnf --all-databases --single-transaction \
  --routines --triggers --events --hex-blob --source-data=2 | gzip -1 > $B/db-all.sql.gz
zcat $B/db-all.sql.gz | tail -1        # harus berisi "Dump completed"

# aplikasi, konfigurasi, dan dokumen
tar -C /var/www/html -czf $B/production.tar.gz production
tar -czf $B/config.tar.gz /etc/httpd /etc/php.ini /etc/php-fpm.d /etc/my.cnf /etc/cron.d
rsync -a /var/data/document-storage/ $B/document-storage/
(cd $B && sha256sum *.gz > SHA256SUMS)

Opsi --single-transaction membuat dump konsisten tanpa mengunci tabel InnoDB. Kemudian --routines --triggers --events memastikan prosedur cetak dan trigger ikut tersimpan. Setelah itu, kami memulihkan dump ke salinan terpisah untuk membuktikan backup benar-benar bisa kita pakai. Saat memulihkan, selalu tambahkan mysql --comments. Tanpa opsi itu, komentar # di dalam prosedur ikut hilang.

Langkah 3: Inventaris Patch Lokal dengan rpm -V

Setiap rumah sakit biasanya punya perbaikan sendiri, misalnya validasi stok obat atau format cetak surat. Untungnya, RPM menyimpan sidik asli setiap file, sehingga perintah rpm -V langsung menunjukkan file yang pernah berubah.

rpm -V simgos > /root/simgos-upg/rpmV.txt
# flag 5 = isi file berbeda dari paket asli
grep '^..5' /root/simgos-upg/rpmV.txt | grep -vE 'data/cache|reports/output|/logs/'

Di server kami, hasilnya 13 file, antara lain app.js, rekammedis.js, dan beberapa file PHP layanan resep. Selain file, kami juga mencatat objek database yang pernah kami ubah, seperti prosedur cetak dan trigger stok opname. Daftar inilah yang nanti kami pasang ulang di atas versi baru.

Langkah 4: Gladi Resik di Salinan Database

Bagian ini paling sering terlewat, padahal justru paling penting. Kami menjalankan MySQL kedua di port 3307 dengan event scheduler mati, lalu memulihkan dump ke sana. Setelah itu, kami menjalankan patch.sh milik vendor apa adanya, hanya port-nya yang kami ganti.

# instance kedua: datadir sendiri, port 3307, event mati
mysqld --defaults-file=/root/simgos-upg/rehearsal.cnf --initialize-insecure --user=mysql
nohup mysqld --defaults-file=/root/simgos-upg/rehearsal.cnf --user=mysql &
zcat $B/db-all.sql.gz | mysql -S /var/lib/mysql-rehearsal/mysql.sock -uroot --comments

# patch.sh vendor dengan port 3307 dan tampilan warning
cd /root/simgos-upg/gladi/db/patchs
sed -i -e 's/^port=3306$/port=3307/' \
  -e 's|--comments < $sql|--comments --show-warnings < $sql|' patch.sh
bash patch.sh "2.6.11-25121200" > ../../core.log 2>&1

Opsi --show-warnings ternyata menyelamatkan kami. Akibatnya, kami bisa menangkap satu baris Data truncated yang biasanya lewat tanpa suara.

Hasil gladi resik upgrade SIMGOS: 880 SQL patch dan satu konfigurasi terpotong
Screenshot asli gladi resik. Nama host tersensor.

Hasilnya, 880 file SQL selesai dalam sekitar satu menit. Namun, gladi resik juga membongkar beberapa masalah yang kami bahas di bagian Contoh Kasus.

Langkah 5: Pasang Ulang Patch Lokal di Atas Kode Baru

Menyalin file lama ke atas versi baru adalah kesalahan klasik, karena kode vendor ikut mundur. Oleh karena itu, kami memasang ulang setiap perubahan di atas kode 2.7.9 dengan tiga cara berbeda.

  • File PHP memakai merge tiga arah: versi asli 2.6.11, versi rumah sakit, dan versi baru 2.7.9.
  • File JavaScript minified kami ubah dulu ke bentuk kanonik lewat parser (acorn + astring), lalu setiap patch kami terapkan sebagai aturan cari-ganti dengan jumlah temuan wajib.
  • Prosedur database kami ambil dari server lama tepat sebelum upgrade, lalu kami pasang lagi sesudah patch vendor.
# merge tiga arah untuk satu file PHP
diff3 -m versi-rs.php versi-asli-2.6.11.php versi-baru-2.7.9.php > hasil.php
php -l hasil.php

Untuk JavaScript, pendekatan kanonik penting karena nama variabel berubah di setiap build. Misalnya, variabel t di versi lama bisa menjadi u di versi baru. Karena itu, setiap aturan patch harus menemukan pola yang tepat dan unik. Bila jumlahnya tidak cocok, skrip berhenti dan tidak menulis file apa pun.

Persiapan Hari H: Jadwal dan Komunikasi

Upgrade SIMGOS bukan sekadar urusan server. Rumah sakit tetap buka saat Anda bekerja, jadi koordinasi dengan petugas sama pentingnya dengan perintah di terminal. Berikut checklist yang kami pakai sebelum menekan tombol eksekusi.

  • Pilih jam paling sepi. Lihat access log beberapa hari terakhir, lalu cari jam dengan request paling sedikit. Di rumah sakit kami, jam sepi jatuh lewat tengah malam.
  • Beri tahu unit yang buka 24 jam. IGD, farmasi, kasir, dan rawat inap perlu tahu kapan SIMGOS berhenti, serta cara mencatat manual sementara.
  • Minta persetujuan pimpinan. Downtime di rumah sakit adalah keputusan layanan, bukan keputusan teknis semata.
  • Siapkan skrip, bukan ingatan. Semua langkah cutover dan rollback harus tertulis dalam skrip yang sudah lolos gladi resik.
  • Tentukan batas waktu. Misalnya, bila uji inti belum lolos dalam satu jam, tim langsung menjalankan rollback.

Dengan checklist ini, petugas tidak kaget saat layanan berhenti. Selain itu, tim IT tidak perlu mengambil keputusan besar di bawah tekanan, karena semua pilihan sudah tersedia sejak awal.

Langkah 6: Cutover dan Uji Asap

Setelah gladi resik lolos, barulah kami menyentuh server produksi. Kami menghentikan cron dan httpd, mematikan event scheduler, lalu mengambil backup final. Kemudian, kami menaikkan PHP lebih dulu dengan cara yang aman.

# PHP 7.4 -> 8.2 dalam SATU transaksi: gagal unduh = tidak ada yang berubah
dnf -y module switch-to php:remi-8.2
php -v | head -1

# karena PHP sudah 8.2, skrip vendor melewati php_74_to_82.sh
dnf -y install /root/simgos-upg/rpm/simgos-2.7.9-26101200.x86_64.rpm
dnf -y install /root/simgos-upg/plugins/*.rpm
cat /var/log/simgos-test.txt     # build patch DB terakhir

mysql --defaults-file=/root/.my-root.cnf --comments < pasca-patch.sql
cp -a /root/simgos-upg/final/. /var/www/html/production/webapps/
systemctl restart php-fpm && systemctl start httpd crond

Urutan ini sengaja kami pilih. Perintah module switch-to mengganti 20 paket PHP dalam satu transaksi, sehingga server tidak pernah tertinggal tanpa PHP. Selanjutnya, skrip uji asap memeriksa HTTP, jumlah baris tabel utama, dan error log.

Hasil cutover upgrade SIMGOS: semua layanan aktif dan jumlah baris tabel sama
Screenshot asli akhir cutover. Jumlah baris tersensor, yang penting angkanya sama.

Contoh Kasus 1: Konfigurasi SATUSEHAT Terpotong Diam-diam

Salah satu file patch vendor menambahkan kunci webhook ke konfigurasi SATUSEHAT memakai JSON_MERGE_PATCH. Masalahnya, kolom VALUE hanya varchar(1000). Karena sql_mode server tidak strict, MySQL memotong teks JSON di karakter ke-1000 tanpa error.

-- cek setelah patch: panjang dan validitas JSON
SELECT ID, LENGTH(VALUE), JSON_VALID(VALUE)
FROM aplikasi.properti_config WHERE ID = 113;
-- produksi: 763, 1   salinan setelah patch: 1000, 0

Akibatnya, fitur yang membaca konfigurasi ini akan gagal tanpa pesan. Solusinya, kami menyimpan nilai asli dalam bentuk HEX sebelum patch, lalu mengembalikannya lewat pasca-patch.sql. Pelajarannya: selalu cek JSON_VALID dan panjang kolom setelah patch database.

Contoh Kasus 2: Logo Rumah Sakit Berubah Jadi Logo Vendor

Beberapa menit setelah upgrade, petugas melapor bahwa logo di halaman login berubah menjadi logo rumah sakit lain. Lebih aneh lagi, setiap kali petugas mengunggah logo baru, tampilannya kembali ke logo yang sama.

Bug setelah upgrade SIMGOS: halaman Pengaturan Instansi menampilkan logo bawaan vendor
Screenshot asli. Nama RS, email, dan website tersensor.

Ternyata file upload tersimpan dengan benar. Masalahnya ada di fungsi baru ImagePath::resolve() yang menolak nama file bukan string. Sejak PHP 8.1, PDO MySQL mengembalikan kolom angka sebagai integer. Akibatnya, ID faskes terbaca sebagai angka, fungsi menolaknya, lalu aplikasi memakai logo cadangan.

public static function resolve($dir, $nama, $ext) {
    // PHP 8.1+: ID dari database berupa int, ubah ke string sebelum diperiksa
    if (is_int($nama) && $nama >= 0) $nama = (string) $nama;
    if (!is_string($nama) || !is_string($ext) || !isset(self::MIME[$ext])) return null;
    // ... validasi nama dan path tetap sama ketatnya
}

Perbaikannya cukup satu baris, dan pengamanan path tetap utuh. Setelah itu, endpoint logo kembali mengirim logo asli rumah sakit.

Uji endpoint logo setelah perbaikan bug PHP 8 pada upgrade SIMGOS
Screenshot asli uji logo. ID faskes dan nama host tersensor.

Jebakan Lain dari Skrip Vendor

Selain dua kasus di atas, gladi resik dan cutover memunculkan beberapa jebakan lain. Berikut ringkasannya, lengkap dengan cara kami menanganinya.

JebakanAkibatPenanganan
php.conf baru merutekan ke 6 pool FPM yang tidak pernah terbentukTagihan, report, BPJS error 503Pertahankan php.conf lama
Vendor menimpa prosedur cetak USG dan surat sehatBug lama muncul lagi di hasil cetakPasang ulang prosedur lokal
Skrip memindahkan file kunci rpmdbdnf install keluar non-zero walau suksesCek versi dan log patch, lalu lanjut
Hak akses folder berubah ke 755Cache, log, dan report gagal tertulisKembalikan mode folder semula
Plugin membaca password dari file sementaraPatch plugin keluar diam-diamPasang inti dulu, baru plugin

Kesalahan Umum

  • Menjalankan dnf update langsung di produksi tanpa membaca skrip instalasi paket.
  • Membuat backup tanpa pernah menguji restore-nya.
  • Menyalin file lama ke atas versi baru, sehingga perbaikan vendor ikut hilang.
  • Mengabaikan warning MySQL, padahal di situlah data terpotong terlihat.
  • Menaikkan PHP dengan cara hapus lalu pasang ulang dari internet.
  • Tidak menyiapkan skrip rollback sebelum cutover.
  • Menganggap upgrade selesai tanpa memantau error log dan laporan petugas di jam ramai.

Kesimpulan

Upgrade SIMGOS yang aman tidak bergantung pada keberuntungan. Kuncinya ada pada urutan kerja: pelajari paket tanpa memasang, backup tiga lokasi, gladi resik di salinan, pasang ulang patch lokal di atas kode baru, lalu cutover dengan skrip yang berhenti sendiri. Dengan alur ini, kami melompati enam rilis sekaligus dengan downtime sekitar 3,5 menit dan tanpa kehilangan satu baris data pun.

Terakhir, catat setiap jebakan yang Anda temukan. Upgrade berikutnya pasti datang, dan catatan hari ini akan memangkas pekerjaan Anda menjadi separuhnya.

Baca Juga

Referensi: MySQL 8.0: mysqldump, RPM: rpm(8) verify, DNF: module command, PHP 8.1: perubahan tidak kompatibel.

Ali Akbar

Software Developer yang fokus mengembangkan aplikasi berbasis Web dan Desktop. Senang mempelajari teknologi baru terutama di bidang web design dan web development.

View all posts by Ali Akbar →

Tinggalkan Balasan

Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib ditandai *