Arsitektur Infrastruktur Edunusa
Dokumen ini menjelaskan bagaimana platform pendidikan digital itn-edunusa berjalan:
mulai dari kode yang ditulis developer, sampai menjadi layanan yang dipakai pengguna,
termasuk siapa saja yang boleh mengaksesnya dan bagaimana semuanya dipantau.
Cara baca: pilih tingkat detail yang Anda butuhkan.
Mode Lengkap menampilkan nama teknis, alamat IP, dan konfigurasi.
00Ringkasan
Lima kalimat yang menjelaskan seluruh sistem. Sisanya hanya memperdalam bagian ini.
Video ringkasan · versi Desktop · buka di tab baru
Bayangkan sebuah gedung kantor. Proxmox adalah tanahnya, satu mesin virtual adalah gedungnya, dan Docker adalah rak-rak di dalam gedung yang masing-masing berisi satu aplikasi. Traefik adalah resepsionis yang mengarahkan setiap tamu ke ruangan yang benar, Kong adalah loket khusus yang hanya melayani permintaan data, dan Vault adalah brankas kunci yang tidak boleh dibuka sembarang orang.
- Developer menulis kode dan mendorongnya ke GitHub. Tidak ada yang di-upload manual ke server.
- GitHub Actions membangun aplikasi menjadi image, yaitu paket siap jalan, lalu menyimpannya di GHCR.
- Server menarik image itu dan menjalankannya sebagai container, satu container per layanan per environment.
- Pengguna masuk lewat Traefik. Halaman web dilayani langsung, sedangkan permintaan data lewat Kong dulu.
- Semua yang terjadi tercatat. Log tiap container dikumpulkan Vector, disimpan VictoriaLogs, dan dilihat di Grafana.
Tiga environment
production untuk pengguna nyata, staging untuk uji coba sebelum rilis, development untuk tim internal. Ketiganya terpisah, termasuk database-nya.
Satu server, banyak container
Semuanya berjalan di satu mesin virtual. Tidak ada Kubernetes. Pemisahan antar layanan dilakukan lewat container dan jaringan Docker.
Dua pintu masuk
Publik hanya bisa membuka production dan staging. Sisanya, termasuk semua alat internal, wajib lewat VPN kantor.
01Lapisan platform
Di mana sebenarnya semua ini berjalan.
Server fisiknya tidak dipakai langsung. Di atasnya dijalankan satu komputer virtual bernama
edunusa-tools, dan di dalam komputer virtual itulah semua layanan hidup sebagai container.
Jadi ada empat lapis: server fisik, komputer virtual, Docker, lalu container.
Spesifikasi mesin virtual
| Aspek | Detail |
|---|---|
| Hostname | edunusa-tools |
| Sistem operasi | Ubuntu 24.04.4 LTS x86_64 · kernel 6.8.0-136 |
| Hypervisor | KVM/QEMU — Standard PC i440FX + PIIX (pc-i440fx-10.1) |
| CPU | QEMU Virtual 2.5+ · 32 vCPU @ 2.099 GHz |
| Memori | 19.930 MiB terpakai dari 24.023 MiB |
| Jaringan | 111.221.43.101 (publik/VPN) + bridge Docker 172.17–172.22 |
| Lain-lain | 821 paket dpkg · bash 5.2.21 · uptime ±48 hari |
Konsekuensi: karena semuanya satu mesin virtual, kapasitas RAM adalah batas nyata. Saat ini sekitar 83 persen memori sudah terpakai, jadi penambahan layanan baru perlu dihitung dulu.
02Dari kode ke container
Perjalanan satu perubahan kode sampai berjalan di server.
Developer tidak pernah menyentuh server secara langsung. Mereka cukup mengirim kode ke GitHub, lalu robot otomatis yang mengemas kode itu menjadi paket siap pakai, menyimpannya di gudang, dan menyuruh server mengambil serta menjalankannya.
Apa yang memicu pipeline
Workflow cicd.yml di tiap repo dipicu oleh push ke salah satu dari tiga branch, dan nama branch itulah yang menentukan environment tujuannya:
Tidak ada persetujuan manusia sebelum production. Push ke branch production berjalan terus sampai container di server diganti. Jadi pola yang dipakai di sini adalah Continuous Deployment, bukan Continuous Delivery.
Gerbang persetujuannya sebenarnya sudah tersedia di template — job container_build_push dan deploy punya environment: yang bisa diisi — tetapi nilainya hanya terisi bila use_github_environment (atau variabel repo USE_GITHUB_ENVIRONMENT) dinyalakan. Nilai bawaannya false dan repo belum menyalakannya, sehingga GitHub tidak memasang perlindungan apa pun.
Yang menahan rilis buruk bukan persetujuan, melainkan health check dan rollback otomatis di langkah 8 dan 9 di bawah.
Tahapan yang dijalankan pipeline
- Checkout — kode diambil dari repo yang memicu pipeline.
- Test — pemeriksaan otomatis dijalankan saat Pull Request lewat
ci.pr.yml, sebelum kode digabung. - Security audit — pemeriksaan dependensi sesuai runtime, ditambah Gitleaks untuk memastikan tidak ada rahasia yang ikut ter-commit.
- Build image — kode dikemas menjadi image dengan penanda commit, sehingga setiap build bisa dilacak asal-usulnya.
- Pindai image — Trivy memeriksa kerentanan pada image yang baru dibangun, dan Syft menghasilkan SBOM. Mode bawaannya
strict, artinya temuan yang memenuhi syarat menggagalkan pipeline sebelum image dipakai. - Push ke GHCR — image disimpan di registry. Inilah yang membuat rollback murah, karena versi lama masih tersimpan.
- Deploy — server diperintahkan lewat SSH untuk menarik image dan menjalankan ulang container.
- Health check — container yang baru dipanggil berulang kali sampai membalas kode status yang diharapkan. Jalur internal dan jalur publik diperiksa dengan cara yang berbeda.
- Rollback otomatis — bila ada langkah deploy yang gagal, termasuk health check, pipeline menjalankan
rollback-single-hostuntuk mengembalikan container ke versi sebelumnya tanpa menunggu operator.
Perlu dicatat bahwa langkah 8 adalah pemeriksaan sekali saat deploy, bukan pengawasan yang terus berjalan. Ia menangkap rilis yang gagal, tetapi tidak menangkap container yang memburuk beberapa jam kemudian.
Detail teknis pipeline
Repo itn-edunusa-pipeline-templates adalah satu-satunya sumber kebenaran untuk semua pipeline. Strukturnya berlapis:
Penamaan image mengikuti pola berikut:
| Komponen | Peran |
|---|---|
| ci.pr.yml | Workflow CI yang berjalan pada Pull Request. |
| cicd.yml | Workflow konsumen di tiap repo. Dipicu push ke development, staging, atau production, lalu memanggil template yang sesuai. |
| container-build-push | Membangun image, memindainya dengan Trivy, menghasilkan SBOM lewat Syft, lalu mendorongnya ke registry. |
| gitleaks-scan | Memeriksa apakah ada rahasia yang ikut ter-commit. |
| deploy-single-host | Action yang menjalankan docker pull dan compose up di server lewat SSH. |
| health-check-frontend | Memanggil ulang container setelah deploy sampai membalas kode status yang diharapkan. Ada versi terpisah untuk jalur internal dan publik, juga untuk backend. |
| rollback-single-host | Dijalankan otomatis dengan if: failure() bila deploy atau health check gagal. |
| rollback-to-tag | Workflow manual untuk kembali ke tag image lama tanpa membangun ulang. |
| ghcr-retention-cleanup | Membersihkan image lama di registry agar tidak menumpuk. |
| Runner self-hosted | Tujuh runner backend dan tujuh runner frontend, berjalan di server yang sama. |
03Vault — pengelolaan rahasia
Password, kunci, dan token disimpan di satu tempat, bukan tersebar di kode.
Vault adalah brankas terpusat. Pipeline tidak menyimpan password di dalam kode atau di GitHub. Setiap kali butuh, pipeline memperkenalkan diri ke Vault dengan sepasang identitas, lalu meminjam rahasia yang diperlukan hanya untuk sekali proses. Brankasnya sendiri hanya bisa dibuka dari jaringan kantor atau VPN.
Apa yang disimpan
- Variabel environment untuk tiap layanan
- Kunci privat SSH untuk deploy
- Token dan API key
- Kubeconfig
Cara pipeline masuk
Memakai AppRole, yaitu pasangan role_id dan secret_id
yang ditukar menjadi token sementara. Nilainya di-mask agar tidak pernah muncul di log build.
Siapa yang boleh membuka
Hanya dari VPN kantor. Dibatasi dua lapis sekaligus: firewall sistem operasi dan daftar IP di Traefik.
| Aspek | Detail |
|---|---|
| Alamat | tools-vault.edunusa.co.id |
| Entrypoint | websecure · sertifikat mytlschallenge |
| Jaringan | traefik-internal |
| Middleware | edunusa-internal-allow@file |
| Allowlist IP | 39.194.0.0/10 (kantor) + 111.221.43.104/32 (OpenVPN) |
| Autentikasi | AppRole (role_id + secret_id), nilai di-mask |
Action yang berhubungan dengan Vault
| Action | Fungsi |
|---|---|
| vault-auth | Login AppRole dan menghasilkan token Vault sementara. |
| fetch-vault-fields | Membaca secret per layanan dari KV store, dipakai sebagai variabel build dan deploy. |
| resolve-ssh-credentials | Mengambil kunci SSH dari Vault, bukan dari GitHub Secrets. |
| resolve-kubeconfig | Mengambil kubeconfig dari Vault. |
04Jalur traffic saat aplikasi dipakai
Ke mana permintaan pengguna mengalir setelah semua container berjalan.
Semua permintaan masuk lewat satu pintu bernama Traefik. Kalau yang diminta adalah halaman web, Traefik langsung menyerahkannya ke container frontend. Kalau yang diminta adalah data, permintaan itu dilewatkan dulu ke Kong sebagai loket pemeriksaan, baru diteruskan ke backend.
Frontend: langsung dari Traefik
Setiap container frontend membawa aturan domainnya sendiri, jadi Traefik tahu container mana yang harus melayani sebuah alamat. Frontend tidak melewati Kong.
Backend: wajib lewat Kong
Container backend sengaja tidak diberi aturan domain di Traefik. Semua akses API melewati Kong, yang menangani autentikasi, pembatasan laju, dan perutean.
Kong terpisah per environment
Ada tiga instans Kong, satu untuk production, staging, dan development. Perubahan aturan di satu environment tidak menyentuh yang lain.
Bukti konfigurasi
Label pada container frontend development, yang menegaskan pembatasan berbasis daftar IP:
Container backend menonaktifkan Traefik sepenuhnya lewat traefik.enable=false,
dan tiap gateway dinamai kong-gateway-{production|staging|development}.
05Siapa boleh mengakses apa
Satu tabel yang menjawab pertanyaan paling sering muncul.
| Komponen | Dari internet | Dari VPN kantor | Catatan |
|---|---|---|---|
| Frontend production | Bisa | Bisa | Tanpa pembatasan IP. |
| Frontend staging | Bisa | Bisa | Tanpa pembatasan IP. |
| Frontend development | Tidak | Bisa | Dibatasi middleware daftar IP. |
| API backend | Lewat Kong | Lewat Kong | Container backend tidak punya rute Traefik sendiri. |
| Vault | Tidak | Bisa | Dibatasi firewall dan daftar IP sekaligus. |
| Grafana | Tidak | Bisa | Dashboard log, port 5000. |
| PostgreSQL | Tidak | Bisa | Untuk operator. Backend mengaksesnya lewat jaringan Docker. |
| MinIO, pgAdmin4, Node-RED, EMQX, OpenWA, Redis | Tidak | Bisa | Semua berada di jaringan traefik-internal. |
Perbedaan penting: pembatasan daftar IP berlaku untuk akses manusia dari luar. Komunikasi antar container di dalam server, misalnya backend membaca database, berjalan di jaringan Docker internal dan tidak melewati pembatasan itu.
Dua lapis pembatasan bekerja bersamaan:
- UFW — firewall di tingkat sistem operasi, berlaku sebelum permintaan sampai ke container.
- Middleware Traefik
edunusa-internal-allow@file— daftar IP39.194.0.0/10(kantor) dan111.221.43.104/32(OpenVPN).
06Data & penyimpanan
Di mana data aplikasi disimpan.
PostgreSQL 18
Tiga instans terpisah, satu per environment. Data production tidak bercampur dengan staging maupun development.
postgresql-database-productionpostgresql-database-stagingpostgresql-database-development
MinIO
Penyimpanan berkas dengan antarmuka yang kompatibel dengan Amazon S3. Bucket dipisah per environment, salah satunya dipakai untuk menyimpan media OpenWA.
07Pencatatan & pemantauan
Bagaimana tim tahu ada yang bermasalah, dan di layanan mana.
Setiap container terus mencetak catatan tentang apa yang sedang dikerjakannya. Vector mengumpulkan semua catatan itu dan memberinya label, misalnya berasal dari environment apa dan layanan mana. VictoriaLogs menyimpannya, lalu Grafana menampilkannya sebagai dashboard yang bisa dicari.
Detail konfigurasi logging
| Tahap | Konfigurasi |
|---|---|
| Sumber 1 | Docker socket unix:///var/run/docker.sock, menangkap stdout dan stderr semua container.
Dikecualikan: portainer, hermes, omniroute. |
| Sumber 2 | HTTP listener pada port 8687, menerima kiriman dari Vector agent di server lain. |
| Pelabelan | environment diturunkan dari akhiran nama container.
log_type memisahkan log aplikasi dari log infrastruktur seperti Postgres, Redis, Vault, MinIO, Kong, dan Traefik.
source_server menandai asal server. |
| Pengiriman | http://victorialogs:9428/insert/elasticsearch/ dengan mode bulk. |
| Stream field terindeks | environment, service, log_type, source_server. |
| Visualisasi | Grafana pada port 5000, dengan VictoriaLogs sebagai datasource. |
08Jaringan Docker
Container dipisahkan ke beberapa jaringan agar akses tidak saling bocor.
| Nama jaringan | Fungsi |
|---|---|
| bridge | Jaringan bawaan Docker. |
| traefik | Container yang dirutekan oleh Traefik, baik publik maupun internal. |
| traefik-external | Tempat frontend, backend, dan Kong terhubung untuk menerima rute Traefik. |
| traefik-internal | Alat internal dan database. Hanya terbuka dari VPN, dengan tambahan daftar IP. |
| kong-* | Jaringan gateway per environment untuk backend. |
09Ringkasan keamanan
Tujuh keputusan yang membentuk postur keamanan sistem ini.
Permukaan publik sengaja sempit
Dari internet, hanya frontend production dan staging yang terbuka. Semua sisanya tertutup.
Pembatasan berlapis dua
Firewall sistem operasi dan daftar IP di Traefik bekerja bersamaan. Satu lapis gagal, lapis lain masih menahan.
Rahasia terpusat
Semua kredensial hanya ada di Vault, tidak di repo dan tidak di GitHub Secrets. Nilainya di-mask agar tidak bocor lewat log build.
Image hanya dari CI
Container hanya boleh berjalan dari image yang dibangun pipeline dan tersimpan di GHCR. Tidak ada build manual di server.
Image dipindai sebelum dipakai
Trivy memeriksa kerentanan tiap image yang baru dibangun, dengan mode bawaan
strict sehingga temuan yang memenuhi syarat menggagalkan pipeline.
Syft menghasilkan SBOM, dan Gitleaks menjaga agar rahasia tidak ikut ter-commit.
Enkripsi otomatis
Semua alamat *.edunusa.co.id memakai TLS yang diperbarui Traefik secara otomatis.
Pemulihan cepat
Deploy yang gagal health check dikembalikan sendiri oleh pipeline lewat
rollback-single-host. Untuk pemulihan yang disengaja, tersedia
rollback-to-tag ke tag image lama tanpa build ulang.
Belum ada gerbang sebelum production
Push ke branch production langsung ter-deploy tanpa persetujuan.
Perlindungan environment GitHub sudah tersedia di template tetapi belum dinyalakan.
Ini titik terlemah pada postur rilis, bukan pada postur jaringan.
Environment terisolasi
Frontend, backend, gateway, dan database dipisah per environment, sehingga percobaan di development tidak menyentuh data production.
10Glosarium
Istilah yang muncul di dokumen ini, dijelaskan tanpa jargon.
https. Sertifikatnya diambil dan diperbarui otomatis oleh Traefik.11Catatan sumber
Dari mana isi dokumen ini berasal, dan apa yang belum terverifikasi.
Sumber kebenaran
- Kondisi aktual server, diambil pada 8 September 2026.
- Berkas workflow di repo
itn-edunusa-pipeline-templatesdancicd.ymlmilik repo konsumen, dibaca langsung pada 12 September 2026. - Label Traefik yang terpasang pada container yang sedang berjalan.
- Keluaran
neofetchpada mesin virtualedunusa-tools.
Koreksi 12 September 2026. Versi sebelumnya menjelaskan tahapan pipeline tanpa menyebut pemicunya,
sehingga mudah dibaca seolah-olah rilis ke production melewati persetujuan. Setelah berkas workflow dibaca
langsung, ternyata push ke branch production berjalan sampai deploy tanpa gerbang apa pun.
Pada kesempatan yang sama ditemukan pula tiga langkah yang sudah berjalan tetapi belum pernah
didokumentasikan: pemindaian image oleh Trivy, pembuatan SBOM oleh Syft, serta health check yang
diikuti rollback otomatis. Bagian 02 dan 09 sudah diperbarui.
Belum terverifikasi
- Apakah API backend environment development juga dibatasi daftar IP seperti frontend-nya.
- Apakah container frontend memanggil backend langsung lewat jaringan Docker, selain lewat Kong.
- Kebijakan retensi log di VictoriaLogs, yaitu berapa lama log disimpan sebelum dihapus.
- Prosedur backup dan pemulihan PostgreSQL serta MinIO.
- Apakah variabel repo
USE_GITHUB_ENVIRONMENTatauIMAGE_SECURITY_MODEdiisi di setelan GitHub. Keduanya tidak terlihat dari berkas dan hanya bisa dipastikan dari halaman setelan repo. Dokumen ini menganggap keduanya memakai nilai bawaan, yaitu gerbang environment mati dan pemindaian imagestrict. - Apakah seluruh repo memanggil template versi
@v2yang sama. Yang diperiksa baruitn-edunusa-sso-fe.
Cara memperbarui dokumen ini: setiap perubahan pada label Traefik, penambahan environment, atau perubahan alur pipeline perlu tercermin di sini. Ubah juga tanggal verifikasi di bagian atas agar pembaca tahu seberapa baru isinya.