Commit 3790712c by Bambang Adrian

chore(doc): remove some unused contents and add some used git scenarios

parent 320f0bcf
......@@ -5,9 +5,9 @@ Dokumen ini menjelaskan langkah-langkah lengkap untuk mempublikasikan layanan OS
#### **Premis dan Kompromi Utama**
Tujuan kita adalah membuat layanan dapat diakses melalui domain publik `geotency.com`, sementara domain teknis yang terhubung ke Cloudflare adalah `diffsquare.web.id`.
Tujuan proses ini adalah membuat layanan dapat diakses melalui domain publik `geotency.com`, sementara domain teknis yang terhubung ke Cloudflare adalah `diffsquare.web.id`.
Karena batasan pada **Cloudflare Free Tier**, kita tidak bisa menggunakan `CNAME` dari domain eksternal (`geotency.com`) untuk menyembunyikan domain teknis. Oleh karena itu, kita akan menggunakan solusi **URL Redirect (Pengalihan URL)**.
Karena batasan pada **Cloudflare Free Tier**, proses ini tidak bisa menggunakan `CNAME` dari domain eksternal (`geotency.com`) untuk menyembunyikan domain teknis. Oleh karena itu, proses ini akan menggunakan solusi **URL Redirect (Pengalihan URL)**.
**Konsekuensi Penting:** Saat pengguna mengakses `https://osrm.geotency.com`, bilah alamat di browser mereka akan **otomatis berubah** menjadi `https://osrm.diffsquare.web.id`. Ini adalah kompromi yang tidak bisa dihindari pada paket Free.
......@@ -191,6 +191,4 @@ Karena batasan pada **Cloudflare Free Tier**, kita tidak bisa menggunakan `CNAME
2. **Tes Routing:** Di halaman `https://osrm.diffsquare.web.id`, coba lakukan routing. Buka *developer tools* (F12) dan pastikan permintaan XHR ditujukan ke `https://route.diffsquare.web.id` dan berhasil (Status 200 OK).
3. **Akses Publik (Uji Redirect):** Buka browser dalam mode penyamaran (incognito).
* Ketik `https://osrm.geotency.com` dan tekan Enter. Bilah alamat **harus berubah** menjadi `https://osrm.diffsquare.web.id` dan menampilkan frontend.
* Ketik `https://route.geotency.com` dan tekan Enter. Bilah alamat **harus berubah** menjadi `https://route.diffsquare.web.id` dan menampilkan respons JSON.
Jika semua verifikasi ini berhasil, maka seluruh sistem telah dikonfigurasi dengan benar sesuai dengan batasan dan tujuan yang ada.
\ No newline at end of file
* Ketik `https://route.geotency.com` dan tekan Enter. Bilah alamat **harus berubah** menjadi `https://route.diffsquare.web.id` dan menampilkan respons JSON.
\ No newline at end of file
......@@ -113,11 +113,11 @@ Untuk memastikan semuanya sudah bersih:
### **Analisis Situasi**
Mari kita bedah apa artinya ini:
Mari proses ini bedah apa artinya ini:
1. **Dua Instalasi yang Berkonflik**: saat ini memiliki dua "mode" `cloudflared` yang ter-setup:
* **Mode Sistem (Yang Sedang Aktif)**: Dikelola dengan `sudo systemctl`, konfigurasinya berada di `/etc/cloudflared/config.yml`, dan berjalan sebagai user `root`. Inilah yang ditunjukkan oleh output.
* **Mode User/Rootless (Yang Kita Tuju)**: Dikelola dengan `systemctl --user`, konfigurasinya berada di `~/.cloudflared/config.yml`, dan berjalan sebagai user `sysadmin`.
* **Mode User/Rootless (Yang proses ini Tuju)**: Dikelola dengan `systemctl --user`, konfigurasinya berada di `~/.cloudflared/config.yml`, dan berjalan sebagai user `sysadmin`.
2. **Sumber Masalah**: Service level sistem ini kemungkinan besar adalah sisa dari instalasi sebelumnya atau dari mengikuti panduan yang berbeda. Karena service ini sudah `enabled` dan `active`, ia akan selalu berjalan di latar belakang dan bisa menyebabkan:
* **Kebingungan**: mungkin mengedit file di `~/.cloudflared/config.yml`, tetapi `cloudflared` yang aktif justru membaca dari `/etc/cloudflared/config.yml`.
......@@ -126,11 +126,11 @@ Mari kita bedah apa artinya ini:
### **Rekomendasi Solusi**
Untuk menjaga konsistensi dengan tujuan setup rootless kita dan untuk menghindari semua potensi konflik, sangat disarankan untuk **menonaktifkan dan menghapus service level sistem ini**. Dengan begitu, kita bisa memastikan bahwa satu-satunya `cloudflared` yang berjalan adalah yang kita kelola sebagai user `sysadmin`.
Untuk menjaga konsistensi dengan tujuan setup rootless proses ini dan untuk menghindari semua potensi konflik, sangat disarankan untuk **menonaktifkan dan menghapus service level sistem ini**. Dengan begitu, proses ini bisa memastikan bahwa satu-satunya `cloudflared` yang berjalan adalah yang proses ini kelola sebagai user `sysadmin`.
### **Langkah-Langkah untuk Menonaktifkan Service Sistem**
Silakan jalankan perintah berikut secara berurutan. Perhatikan penggunaan `sudo` karena kita berinteraksi dengan service sistem.
Silakan jalankan perintah berikut secara berurutan. Perhatikan penggunaan `sudo` karena proses ini berinteraksi dengan service sistem.
1. **Hentikan Service Sistem:**
Perintah ini akan menghentikan proses `cloudflared` (PID 1571) yang sedang berjalan.
......@@ -170,4 +170,4 @@ sudo mv /etc/cloudflared /etc/cloudflared.backup
### **Langkah Berikutnya**
Setelah service sistem ini tidak aktif, kita bisa melanjutkan proses penghapusan tunnel dari sisi *user* (rootless) seperti yang kita diskusikan di pesan sebelumnya, tanpa ada gangguan dari proses lain. sekarang memiliki kontrol penuh atas proses `cloudflared` yang berjalan sebagai user.
\ No newline at end of file
Setelah service sistem ini tidak aktif, lanjutkan proses penghapusan tunnel dari sisi *user* (rootless) seperti yang proses ini diskusikan di pesan sebelumnya, tanpa ada gangguan dari proses lain. sekarang memiliki kontrol penuh atas proses `cloudflared` yang berjalan sebagai user.
\ No newline at end of file
## Dokumentasi Operasi Git
### **Daftar Isi**
1. [Inisialisasi dan Publikasi Repositori ke GitLab](#1-inisialisasi-dan-publikasi-repositori-ke-gitlab)
2. [Manajemen Branch (Cabang)](#2-manajemen-branch-cabang)
3. [Modifikasi Riwayat Commit yang Sudah Dipublikasikan](#3-modifikasi-riwayat-commit-yang-sudah-dipublikasikan)
4. [Membatalkan Operasi `rebase`](#4-membatalkan-operasi-rebase)
---
### **1. Inisialisasi dan Publikasi Repositori ke GitLab**
Bagian ini menjelaskan alur kerja standar untuk mempublikasikan proyek lokal yang baru dibuat ke repositori GitLab yang di-hosting sendiri (self-hosted).
* **Tujuan:** Mengunggah kode dari direktori lokal yang sudah diinisialisasi (`git init`) ke sebuah proyek baru di GitLab.
#### **Langkah-langkah Skenario**
**Langkah 1.1: Membuat Proyek Baru di GitLab**
Sebelum menghubungkan repositori lokal, harus memiliki tujuan (remote repository) di GitLab.
1. Masuk ke instance GitLab.
2. Pada dasbor, klik tombol **"New project"**.
3. Pilih opsi **"Create blank project"**.
4. Isi detail proyek seperti "Project name". Pastikan "Initialize repository with a README" **tidak dicentang**, karena sudah memiliki repositori lokal.
5. Klik **"Create project"**.
**Langkah 1.2: Menghubungkan Repositori Lokal ke Remote GitLab**
Setelah proyek dibuat, GitLab akan memberikan URL. Gunakan URL ini untuk menghubungkan direktori lokal.
1. Buka terminal atau command prompt pada direktori kerja.
2. Jalankan perintah berikut untuk menambahkan remote. Ganti `<URL_PROYEK_GITLAB_ANDA>` dengan URL HTTPS atau SSH yang dapatkan dari GitLab.
```bash
git remote add origin <URL_PROYEK_GITLAB_ANDA>
```
**Langkah 1.3: Melakukan Commit dan Push Perdana**
Langkah terakhir adalah menambahkan file, membuat "snapshot" (commit), dan mendorongnya ke GitLab.
1. Tambahkan semua file di direktori kerja ke area *staging*.
```bash
git add .
```
2. Buat commit pertama dengan pesan yang deskriptif.
```bash
git commit -m "Initial commit"
```
3. Dorong (push) commit dari branch lokal ke remote `origin`. Opsi `-u` akan mengatur pelacakan (upstream) sehingga untuk selanjutnya cukup menggunakan `git push`.
* Jika branch default lokal bernama `main`:
```bash
git push -u origin main
```
* Jika branch default lokal bernama `master`:
```bash
git push -u origin master
```
---
### **2. Manajemen Branch (Cabang)**
Bagian ini mencakup operasi dasar dan penanganan masalah terkait branch di lingkungan lokal dan remote.
#### **Skenario 2.1: Menghapus Branch di Lokal dan Remote**
* **Tujuan:** Menghapus branch yang sudah tidak diperlukan lagi dari repositori lokal dan dari server GitLab.
**Langkah-langkah:**
1. Pastikan tidak sedang berada di branch yang akan dihapus. Pindah ke branch lain, misalnya `master`.
```bash
git checkout master
```
2. Hapus branch dari repositori lokal.
```bash
# Gunakan -d untuk menghapus secara aman (hanya jika sudah di-merge)
git branch -d <nama-branch-yang-dihapus>
# Gunakan -D untuk memaksa penghapusan (jika belum di-merge)
git branch -D <nama-branch-yang-dihapus>
```
3. Hapus branch dari remote `origin` (GitLab).
```bash
git push origin --delete <nama-branch-yang-dihapus>
```
#### **Skenario 2.2: Membuat dan Mendorong Branch Baru**
* **Tujuan:** Membuat branch baru untuk pengembangan fitur atau perbaikan, lalu mempublikasikannya ke GitLab.
**Langkah-langkah:**
1. Buat branch baru dan langsung berpindah ke dalamnya.
```bash
git checkout -b <nama-branch-baru>
```
2. Lakukan pekerjaan (ubah, tambah, hapus file), lalu commit perubahan tersebut.
```bash
git add .
git commit -m "Deskripsi perubahan pada branch baru"
```
3. Dorong branch baru ke remote `origin` dan atur pelacakan (upstream).
```bash
git push -u origin <nama-branch-baru>
```
#### **Skenario 2.3: Mengatasi Error "The default branch cannot be deleted"**
* **Tujuan:** Menghapus branch yang saat ini diatur sebagai *default branch* di GitLab.
**Penjelasan Masalah:**
GitLab melindungi branch default (misalnya `main` atau `master`) agar tidak bisa dihapus secara langsung melalui `git push --delete`. Ini untuk mencegah repositori kehilangan branch utamanya.
**Langkah-langkah Solusi:**
1. **Buat Calon Default Branch Baru:** Jika belum ada, buat branch baru (misalnya `master`) dari branch default saat ini (`main`) dan dorong ke GitLab.
```bash
# Pastikan basisnya sama dengan branch default saat ini
git checkout main
git pull origin main
# Buat branch baru dan push
git checkout -b master
git push -u origin master
```
2. **Ubah Default Branch di Antarmuka GitLab:**
1. Buka proyek di GitLab.
2. Navigasi ke **Settings > Repository**.
3. Perluas (expand) bagian **Default branch**.
4. Ubah branch default dari `main` ke `master`.
5. Klik **Save changes**.
3. **Hapus Branch Default yang Lama:** Setelah tidak lagi menjadi default, kini bisa menghapusnya dari remote.
```bash
git push origin --delete main
```4. **(Opsional) Hapus Branch Lokal yang Lama:**
```bash
# Pindah ke branch default yang baru
git checkout master
# Hapus branch lama dari lokal
git branch -D main
```
---
### **3. Modifikasi Riwayat Commit yang Sudah Dipublikasikan**
Bagian ini membahas teknik `interactive rebase` untuk mengubah riwayat commit yang sudah ada di remote.
> **PERINGATAN KERAS:**
> Mengubah riwayat commit yang sudah dipublikasikan (`push`) adalah tindakan yang **berisiko** dan dapat menyebabkan masalah besar bagi kolaborator lain. Gunakan perintah di bagian ini hanya jika **100% yakin** bahwa adalah satu-satunya orang yang bekerja pada branch tersebut, atau jika seluruh tim telah setuju dan memahami konsekuensinya. Operasi ini memerlukan `force push`, yang akan menimpa riwayat di server.
#### **Skenario 3.1: Menggabungkan Dua Commit Terakhir (Squash)**
* **Tujuan:** Membersihkan riwayat dengan menggabungkan beberapa commit kecil (misalnya, "perbaikan typo" dan "perubahan kecil") menjadi satu commit yang lebih bermakna.
**Langkah-langkah:**
1. Mulai *interactive rebase* untuk 2 commit terakhir dari posisi `HEAD`.
```bash
git rebase -i HEAD~2
```
2. Editor teks akan terbuka. Ubah kata `pick` pada baris kedua (commit yang lebih baru) menjadi `squash` atau `s`.
```
# Ubah ini:
pick 600c66c3 chore(doc): remove some unused contents
pick 3d79be0a chore(doc): remove some unused contents
# Menjadi ini:
pick 600c66c3 chore(doc): remove some unused contents
squash 3d79be0a chore(doc): remove some unused contents
```
3. Simpan dan tutup editor.
4. Editor teks kedua akan terbuka, berisi gabungan pesan dari kedua commit. Tulis ulang pesan commit menjadi satu pesan yang jelas dan ringkas.
5. Simpan dan tutup editor.
6. Paksa dorong (force push) perubahan ke remote. Menggunakan `--force-with-lease` lebih aman daripada `--force` biasa karena akan memeriksa apakah ada orang lain yang sudah mendorong perubahan ke branch tersebut.
```bash
git push --force-with-lease origin master
```
#### **Skenario 3.2: Mengubah Pesan Commit yang Lama (Reword)**
* **Tujuan:** Memperbaiki kesalahan ketik (typo) atau memperjelas pesan pada commit yang sudah lama terpendam dalam riwayat.
**Langkah-langkah:**
1. Identifikasi ID commit yang berada **tepat sebelum** commit yang pesannya ingin ubah. Gunakan `git log`.
```bash
git log --oneline
```
2. Mulai *interactive rebase* menggunakan ID commit yang identifikasi tersebut.
```bash
git rebase -i <ID-COMMIT-SEBELUMNYA>
```
3. Editor teks akan terbuka. Cari baris dengan commit yang ingin ubah, lalu ganti kata `pick` menjadi `reword` atau `r`.
```
# Ubah ini:
pick c5dadb4 fix(osrm): self containded script...
# Menjadi ini:
reword c5dadb4 fix(osrm): self containded script...
```
4. Simpan dan tutup editor.
5. Editor teks baru akan segera terbuka, hanya berisi pesan commit yang salah. Perbaiki pesan tersebut.
6. Simpan dan tutup editor. Git akan menyelesaikan sisa proses rebase.
7. Paksa dorong (force push) perubahan ke remote.
```bash
git push --force-with-lease origin master
```
---
### **4. Membatalkan Operasi `rebase`**
Jika membuat kesalahan selama proses `rebase`, penting untuk mengetahui cara membatalkannya dengan aman.
#### **Skenario 4.1: Membatalkan `rebase` yang Sedang Berjalan**
* **Tujuan:** Menghentikan proses `rebase` setelah dimulai (misalnya, setelah menyimpan file interaktif pertama) dan mengembalikan repositori ke keadaan semula.
**Perintah:**
Jalankan perintah ini kapan saja selama proses rebase (misalnya, saat terjadi konflik atau saat diminta mengedit pesan commit).
```bash
git rebase --abort
```
Perintah ini akan sepenuhnya membatalkan `rebase` dan membersihkan status repositori kembali seperti sebelum `rebase` dimulai.
#### **Skenario 4.2: Membatalkan `rebase` dari Editor Teks Interaktif Awal**
* **Tujuan:** Membatalkan `rebase` saat pertama kali melihat daftar `pick` di editor dan menyadari telah membuat kesalahan (misalnya, salah memilih ID commit).
**Cara Membatalkan:**
tidak perlu perintah khusus. Cukup keluar dari editor **tanpa menyimpan perubahan**.
* **Pada editor Vim/Vi:** Tekan `Esc`, ketik `:q!` lalu tekan `Enter`.
* **Pada editor Nano:** Tekan `Ctrl + X`, dan saat ditanya untuk menyimpan, tekan `N` (untuk "No").
Alternatifnya, juga bisa menghapus semua baris commit di dalam editor, lalu simpan dan tutup file yang kosong tersebut. Git akan menganggap ini sebagai instruksi untuk membatalkan `rebase`.
---
## Dokumentasi Operasi Git Lanjutan (Bagian 2)
Dokumen ini adalah kelanjutan dari kompilasi sebelumnya dan berfokus pada skenario lanjutan terkait modifikasi riwayat commit, penanganan riwayat yang berbeda (divergent history), dan alur kerja yang benar untuk menyinkronkannya dengan remote.
### **Daftar Isi**
1. [Menggabungkan Perubahan Lokal ke Commit Terakhir di Remote](#1-menggabungkan-perubahan-lokal-ke-commit-terakhir-di-remote)
2. [Memahami Masalah "Duplikasi" Commit dan Divergent History](#2-memahami-masalah-duplikasi-commit-dan-divergent-history)
3. [Studi Kasus: Analisis dan Solusi untuk Grafik Git yang Bercabang](#3-studi-kasus-analisis-dan-solusi-untuk-grafik-git-yang-bercabang)
---
### **1. Menggabungkan Perubahan Lokal ke Commit Terakhir di Remote**
Bagian ini membahas cara "menumpuk" pekerjaan baru yang ada di lokal ke dalam commit terakhir yang sudah ada di server, seolah-olah semua pekerjaan itu dilakukan dalam satu waktu.
> **PERINGATAN:** Semua metode di bagian ini menulis ulang riwayat dan memerlukan `git push --force-with-lease`. Pastikan tidak ada anggota tim lain yang bekerja di branch ini atau sudah berkoordinasi.
#### **Skenario 1.1: Menggabungkan Beberapa Commit Lokal Baru**
* **Kondisi:** memiliki beberapa commit baru di lokal (`Commit A, B, C`) di atas commit terakhir dari remote (`Commit AR`).
* **Tujuan:** Menggabungkan `Commit A, B, C` ke dalam `Commit AR` menjadi satu commit tunggal.
**Metode yang Direkomendasikan: `git reset --soft` + `git commit --amend`**
1. **Pindahkan Penanda `HEAD`:** Pindahkan penanda branch ke posisi `Commit AR` tanpa kehilangan perubahan dari commit-commit setelahnya. Jika ada 3 commit baru, gunakan `HEAD~3`.
```bash
# Mundur 3 commit, tapi simpan semua perubahannya di staging area
git reset --soft HEAD~3
```
2. **Periksa Status:** Setelah `reset`, `git status` akan menunjukkan semua perubahan dari 3 commit tersebut sebagai "Changes to be committed".
3. **Gabungkan ke Commit Sebelumnya:** Gunakan `amend` untuk menambahkan semua perubahan yang ada di *staging area* ke commit saat ini (`Commit AR`).
```bash
# Menggabungkan perubahan ke commit terakhir dan membuka editor untuk mengedit pesan
git commit --amend
# Alternatif jika tidak ingin mengubah pesan commit yang sudah ada
git commit --amend --no-edit
```
4. **Paksa Push ke Remote:** Timpa riwayat di remote dengan riwayat baru dari lokal.
```bash
git push --force-with-lease origin <nama-branch>
```
#### **Skenario 1.2: Menambahkan Perubahan yang Belum di-Commit**
* **Kondisi:** memiliki perubahan di direktori kerja (file yang diubah/ditambah) tetapi belum membuat commit baru.
* **Tujuan:** Menambahkan perubahan ini langsung ke commit terakhir di remote.
**Langkah-langkah:**
1. **Tambahkan Perubahan ke Staging Area:**
```bash
git add .
```
2. **Gunakan `commit --amend`:** Langsung gabungkan perubahan yang di-*stage* ke commit terakhir.
```bash
git commit --amend --no-edit
```
3. **Paksa Push ke Remote:**
```bash
git push --force-with-lease origin <nama-branch>
```
---
### **2. Memahami Masalah "Duplikasi" Commit dan Divergent History**
Ini menjelaskan mengapa `git commit --amend` terkadang bisa menyebabkan riwayat yang membingungkan jika tidak ditangani dengan benar.
#### **Konsep Inti: Commit Tidak Dapat Diubah (Immutable)**
Sebuah commit di Git tidak bisa diedit. Saat menjalankan `git commit --amend`, Git membuat **commit yang sama sekali baru** dengan hash ID yang baru, lalu membuang commit yang lama dari riwayat lokal.
#### **Penyebab "Duplikasi" - Alur Kerja yang Salah**
1. **Kondisi Awal:** Lokal dan remote sinkron, keduanya memiliki `Commit A (hash: abc123)`.
2. **Lokal Diubah:** menjalankan `git commit --amend`. Lokal sekarang memiliki `Commit A' (hash: def456)`. Riwayat lokal dan remote kini **berbeda (diverged)**.
3. **Kesalahan Fatal:** menjalankan `git pull`.
* `git pull` mencoba menggabungkan dua riwayat yang berbeda ini.
* Karena tidak bisa digabungkan secara lurus (*fast-forward*), Git akan membuat **merge commit** baru untuk menyatukan kedua cabang tersebut.
4. **Hasil Akhir yang Berantakan:** `git log` akan menampilkan `Commit A` (dari remote) dan `Commit A'` (dari lokal), disatukan oleh sebuah `Merge commit`. Inilah yang terlihat seperti "duplikasi".
#### **Alur Kerja yang Benar**
Setelah melakukan `amend`, riwayat memang sengaja dibuat berbeda. Jangan coba "memperbaikinya" dengan `pull`. Sebaliknya, perintahkan remote untuk menerima versi riwayat.
| Alur Kerja Salah (Menyebabkan Duplikasi) | Alur Kerja Benar (Riwayat Bersih) |
| :--- | :--- |
| 1. `git commit --amend` | 1. `git commit --amend` |
| 2. `git push` (Gagal) | 2. `git push --force-with-lease` |
| 3. `git pull` (Membuat *merge commit*) | |
---
### **3. Studi Kasus: Analisis dan Solusi untuk Grafik Git yang Bercabang**
Bagian ini menganalisis skenario spesifik berdasarkan gambar grafik Git yang berikan.
**Analisis Grafik:**
* **Garis Biru (`master`):** Menunjukkan riwayat branch **lokal**. Commit teratasnya (`4e8ee786`) adalah hasil dari `amend` atau `rebase`.
* **Garis Pink (`origin/master`):** Menunjukkan riwayat branch di **remote**. Commit teratasnya (`e6f2b6a0`) adalah versi asli sebelum mengubahnya.
* **Titik Percabangan:** Grafik dengan jelas menunjukkan titik di mana riwayat lokal dan remote mulai berbeda.
**Kesimpulan dari Grafik:**
telah berhasil menulis ulang riwayat di lokal, tetapi belum menyinkronkannya dengan benar ke remote.
**Solusi Definitif:**
Perintah yang harus jalankan adalah `force push` untuk memaksa remote agar mengikuti riwayat lokal.
```bash
git push --force-with-lease origin master
```
**Hasil Setelah Menjalankan Perintah:**
* Riwayat di `origin/master` yang berujung di commit `e6f2b6a0` akan **dihapus**.
* Riwayat dari `master` lokal yang berujung di commit `4e8ee786` akan diunggah dan menjadi riwayat resmi yang baru di remote.
* Grafik akan kembali menjadi **satu garis lurus yang bersih**, di mana `master` dan `origin/master` menunjuk ke commit yang sama (`4e8ee786`). Tidak akan ada duplikasi atau cabang.
\ No newline at end of file
......@@ -315,17 +315,3 @@ Frontend URL:
Logs stored at: ~/data/docker-data/osrm/logs/osrm-installer-20251015.log
```
---
## 10. Konfirmasi Sebelum Implementasi
Mohon konfirmasi hal berikut:
1. Apakah semua flag dan behavior sudah sesuai (termasuk pemisahan `update-*` & `remove-*`)?
2. Apakah format URL backend `http://{backend-domain}:{backend-port}/osrm/{api-version}/{profile}` sudah final?
3. Apakah lokasi default (`~/data/docker-data/osrm`) boleh di-hardcode dalam skrip (dapat diubah via `--work-dir`)?
4. Apakah backup otomatis (zip sebelum override) tetap diaktifkan?
5. Apakah kamu ingin output tambahan berupa file `config-summary.json` untuk dokumentasi hasil instalasi?
Setelah kamu konfirmasi, saya akan lanjut ke tahap **penulisan bashscript implementasi final** sesuai spesifikasi ini.
......@@ -469,23 +469,3 @@ Output yang tampilkan secara definitif memvalidasi beberapa poin kritis dari skr
4. **Verifikasi Ganda**:
* **Verifikasi Internal**: Langkah "Memverifikasi instalasi..." di dalam skrip berhasil, yang berarti perintah `docker compose version` dapat dijalankan oleh skrip itu sendiri.
* **Verifikasi Manual**: melakukan verifikasi manual pasca-eksekusi dengan `docker compose version`, yang memberikan konfirmasi akhir dan tak terbantahkan bahwa plugin telah terintegrasi dengan benar ke dalam Docker CLI.
### Kesimpulan dan Status Final
Ini adalah studi kasus yang sempurna tentang pentingnya *debugging* dan verifikasi. Laporan bug yang presisi memungkinkan identifikasi dan perbaikan cepat, menghasilkan produk akhir yang jauh lebih kuat.
Dengan ini, saya menyatakan bahwa skrip `install-compose-rootless.sh` versi 2.1, seperti yang terdokumentasi dalam **KB-DEVOPS-2024-001**, telah terverifikasi dan divalidasi untuk penggunaan di lingkungan target. Skrip ini sekarang memenuhi semua spesifikasi yang diminta:
* **Modular dan DRY**: Ya.
* **Dinamis dan Parameterized**: Ya.
* **Verbose dan Dry Run Mode**: Ya, dan sekarang berfungsi dengan benar.
* **Penanganan Error yang Handal**: Ya, terbukti dari perbaikan `set -e`.
* **Validasi dan Pengecekan Lengkap**: Ya.
### Langkah Selanjutnya yang Direkomendasikan
1. **Standarisasi**: Gunakan skrip versi 2.1 ini sebagai standar untuk semua deployment baru.
2. **Version Control**: Simpan skrip ini di dalam repositori Git (misalnya, dalam direktori `scripts` atau `automation`) untuk pelacakan perubahan dan kolaborasi tim.
3. **Integrasi Otomatisasi**: sekarang dapat dengan percaya diri mengintegrasikan skrip ini ke dalam *playbook* Ansible, skrip *provisioning* Terraform, atau pipeline CI/CD lainnya, dengan mengetahui bahwa skrip ini akan berperilaku secara konsisten danl.
Proses ini telah berhasil diselesaikan dengan standar tertinggi. Terima kasih atas kolaborasi yang sangat baik dalam mencapai hasil ini.
\ No newline at end of file
......@@ -235,8 +235,6 @@ main "$@"
Jika melihat pesan "Hello from Docker!", instalasi dan konfigurasi telah berhasil sepenuhnya.
Tentu, saya akan melakukan peninjauan ulang yang sangat detail, baris per baris, dan secara keseluruhan terhadap skrip Bash yang telah saya buat. Tujuannya adalah untuk memastikan skrip ini se-robust mungkin dan bebas dari potensi error atau perilaku yang tidak terduga.
### Tinjauan Keseluruhan
Skrip ini dirancang dengan baik dan sudah menerapkan banyak praktik terbaik dalam scripting Bash:
......@@ -248,7 +246,7 @@ Skrip ini dirancang dengan baik dan sudah menerapkan banyak praktik terbaik dala
### Analisis Detail Baris per Baris
Mari kita bedah setiap bagian penting.
Mari proses ini bedah setiap bagian penting.
---
......@@ -315,7 +313,7 @@ log_error() {
* **`parse_arguments()`**: Logikanya solid. Loop `while`, `case`, dan `shift` adalah pola standar untuk parsing argumen. Validasi `if [[ -z "$USERNAME" ]]` juga sangat penting dan diimplementasikan dengan benar. **Tidak ada error**.
* **`check_prerequisites()`**:
* `if [[ "$EUID" -ne 0 ]]`: Pengecekan hak akses root yang benar dan standar.
* `if ! grep -q ... || ! grep -q ...`: Logika untuk memeriksa OS dan versi sudah benar. Menggunakan `-q` (quiet) efisien karena kita hanya peduli dengan status keluarnya. **Tidak ada error**.
* `if ! grep -q ... || ! grep -q ...`: Logika untuk memeriksa OS dan versi sudah benar. Menggunakan `-q` (quiet) efisien karena proses ini hanya peduli dengan status keluarnya. **Tidak ada error**.
---
......
......@@ -19,7 +19,7 @@
Dokumen ini berfungsi sebagai panduan definitif untuk melakukan instalasi, penyiapan, dan konfigurasi **Nginx Proxy Manager (selanjutnya disebut "ngpm")** pada sistem operasi **Rocky Linux 10**.
* **WHAT (Apa):** Prosedur ini menguraikan deployment ngpm, sebuah antarmuka manajemen berbasis web untuk Nginx yang mempermudah pengelolaan *reverse proxy*, sertifikat SSL/TLS dari Let's Encrypt, dan *custom Nginx configurations* tanpa perlu menyentuh file konfigurasi secara manual.
* **WHY (Mengapa):** Metode ini dipilih karena mengedepankan prinsip keamanan dan isolasi modern. Dengan menjalankan kontainer Docker dalam **mode rootless**, kita secara drastis mengurangi permukaan serangan (*attack surface*). Jika terjadi kompromi pada kontainer, dampaknya terbatas pada lingkup pengguna non-root (`sysadmin`), bukan seluruh sistem. Penggunaan skrip otomasi memastikan proses yang konsisten, dapat diulang (*reproducible*), dan bebas dari kesalahan manusia (*human error*).
* **WHY (Mengapa):** Metode ini dipilih karena mengedepankan prinsip keamanan dan isolasi modern. Dengan menjalankan kontainer Docker dalam **mode rootless**, proses ini secara drastis mengurangi permukaan serangan (*attack surface*). Jika terjadi kompromi pada kontainer, dampaknya terbatas pada lingkup pengguna non-root (`sysadmin`), bukan seluruh sistem. Penggunaan skrip otomasi memastikan proses yang konsisten, dapat diulang (*reproducible*), dan bebas dari kesalahan manusia (*human error*).
* **WHO (Siapa):** Panduan ini ditujukan untuk para profesional teknis seperti System Administrator dan DevOps Engineer yang bertugas mengelola infrastruktur web dan memerlukan solusi *reverse proxy* yang efisien dan aman.
* **WHERE (Di Mana):** Implementasi dilakukan pada server yang menjalankan Rocky Linux 10, dengan prasyarat Docker Engine yang sudah terinstal dan dikonfigurasi untuk mode rootless di bawah pengguna `sysadmin`. Seluruh data persisten dan konfigurasi akan ditempatkan secara terstruktur di dalam direktori `~/data/docker-data/ngpm/`.
* **WHEN (Kapan):** Prosedur ini ideal untuk diterapkan pada lingkungan pengembangan, pengujian, maupun produksi baru di mana diperlukan gerbang (*gateway*) yang aman untuk mengekspos layanan internal ke jaringan publik atau internet.
......@@ -50,7 +50,7 @@ Solusi ini terdiri dari beberapa komponen utama yang bekerja sama dalam sebuah e
#### **3.0 Analisis Prosedur dan Tahapan Kritis**
Skrip otomasi yang akan kita kembangkan akan mengeksekusi serangkaian tahapan yang telah divalidasi secara logis.
Skrip otomasi yang akan proses ini kembangkan akan mengeksekusi serangkaian tahapan yang telah divalidasi secara logis.
1. **Parsing Argumen:** Langkah pertama adalah memproses input dari pengguna. Ini memungkinkan fleksibilitas tinggi tanpa harus mengubah kode skrip. Mode `--dry-run` akan diidentifikasi pada tahap ini.
2. **Pengecekan Pra-Instalasi (Pre-flight Checks):** Tahap paling krusial. Skrip akan memverifikasi:
......@@ -247,17 +247,17 @@ Jika semua verifikasi ini berhasil, maka instalasi dan konfigurasi Nginx Proxy M
#### **7.0 Analisis dan Penyempurnaan Skrip**
Skrip referensi awal sudah cukup baik, namun beberapa area dapat ditingkatkan untuk memenuhi standar perfeksionis dan skeptis yang kita anut. Berikut adalah perubahan kunci dan justifikasinya:
Skrip referensi awal sudah cukup baik, namun beberapa area dapat ditingkatkan untuk memenuhi standar perfeksionis dan skeptis yang proses ini anut. Berikut adalah perubahan kunci dan justifikasinya:
1. **Modularitas:** Fungsi-fungsi telah diorganisir kembali ke dalam blok logis yang lebih jelas: *Helpers*, *Pre-flight*, *Setup*, *Core Logic*, dan *Main Execution*.
2. **Penanganan Parameter:** Penggunaan `getopts` atau loop `case` adalah standar, namun saya akan memastikan validasi input lebih ketat dan pesan kesalahan lebih spesifik untuk setiap argumen yang tidak valid.
2. **Penanganan Parameter:** Penggunaan `getopts` atau loop `case` adalah standar, namun perlu memastikan validasi input lebih ketat dan pesan kesalahan lebih spesifik untuk setiap argumen yang tidak valid.
3. **Robustisitas:**
* **Quoting Variabel:** Semua ekspansi variabel (contoh: `"${PROJECT_DIR}"`) diapit dengan kutip guntuk mencegah masalah dengan spasi atau karakter khusus dalam path atau nama. Ini adalah praktik fundamental yang sering diabaikan.
* **Heredoc Safety:** Penulisan file konfigurasi menggunakan `heredoc` telah diperbaiki untuk menghindari ekspansi variabel yang tidak diinginkan di dalam *template*. Variabel akan diekspansi secara eksplisit dan aman.
* **Error Handling `cd`:** Perintah `cd` dapat gagal. Saya akan memastikan skrip berhenti jika gagal berpindah direktori untuk mencegah eksekusi perintah di lokasi yang salah.
* **Error Handling `cd`:** Perintah `cd` dapat gagal. Skrip berhenti jika gagal berpindah direktori untuk mencegah eksekusi perintah di lokasi yang salah.
4. **Keamanan:**
* **Permissions:** Meskipun tidak diminta secara eksplisit, *best practice* adalah mengatur izin pada file sensitif seperti `.env`. Namun, dalam konteks rootless, risiko ini sudah diminimalkan karena file dimiliki oleh user `sysadmin` dan tidak dapat diakses oleh user lain secara default.
* **Password Handling:** Penggunaan `openssl` untuk *password generation* sudah tepat. Saya akan memastikan tidak ada *logging* password ke stdout kecuali dalam mode `--dry-run` yang sangat eksplisit.
* **Password Handling:** Penggunaan `openssl` untuk *password generation* sudah tepat. Perlu memastikan tidak ada *logging* password ke stdout kecuali dalam mode `--dry-run` yang sangat eksplisit.
5. **Kepatuhan pada Permintaan Spesifik:**
* **Penamaan:** Penggunaan *dash-case* (`kebab-case`) akan diterapkan secara konsisten pada nilai default dan di seluruh dokumentasi. Istilah "ngpm" akan digunakan secara eksklusif.
* **Parameterized Variables:** Semua variabel yang minta telah dijadikan parameter yang dapat di-override melalui argumen CLI.
......@@ -856,7 +856,7 @@ Bagian ini menyediakan instruksi langkah-demi-langkah yang jelas untuk menyimpan
**9.2. Pemberian Izin Eksekusi**
1. **WHY:** Secara default, file baru tidak memiliki izin untuk dieksekusi. Kita harus memberikannya secara eksplisit untuk dapat menjalankan skrip.
1. **WHY:** Secara default, file baru tidak memiliki izin untuk dieksekusi. proses ini harus memberikannya secara eksplisit untuk dapat menjalankan skrip.
2. **HOW:** Gunakan perintah `chmod` untuk menambahkan *flag* eksekusi (`+x`).
```bash
chmod +x install-ngpm.sh
......@@ -1171,6 +1171,3 @@ Berdasarkan anomali healthcheck, berikut adalah langkah-langkah definitif yang h
3. **Periksa Sumber Daya Sistem Host:**
* Jalankan `top` atau `htop` pada server untuk memastikan tidak ada lonjakan CPU atau penggunaan memori yang ekstrem yang dapat memperlambat proses startup Docker container.
**Kesimpulan Akhir:**
Skrip berfungsi dengan sangat baik. Skrip ini tidak hanya melakukan tugasnya tetapi juga cukup cerdas untuk mendeteksi potensi masalah (healthcheck gagal) dan melaporkannya dengan jelas tanpa menghentikan proses secara tidak perlu. Log yang berikan adalah contoh sempurna dari bagaimana otomasi yang robust seharusnya bekerja: **eksekusi, verifikasi, dan pelaporan anomali.**
\ No newline at end of file
......@@ -23,7 +23,7 @@
### **1. Analisis Kebutuhan dan Ringkasan Spesifikasi**
Sebelum memulai implementasi, mari kita rekapitulasi dan validasi seluruh kebutuhan yang telah sampaikan. Ini memastikan keselarasan pemahaman dan menjadi dasar untuk semua keputusan teknis yang akan diambil.
Sebelum memulai implementasi, mari proses ini rekapitulasi dan validasi seluruh kebutuhan yang telah sampaikan. Ini memastikan keselarasan pemahaman dan menjadi dasar untuk semua keputusan teknis yang akan diambil.
#### **1.1. Format Tabular**
......@@ -470,7 +470,7 @@ check_file_exists() {
is_found=true
fi
# Jika dalam mode dry-run dan file tidak ditemukan, kita skip pengecekan fisik.
# Jika dalam mode dry-run dan file tidak ditemukan, proses ini skip pengecekan fisik.
if [ "$DRY_RUN" = "true" ] && ! $is_found; then
check_status="${COLOR_YELLOW}Skipped${COLOR_RESET}"
fi
......@@ -948,7 +948,7 @@ main "$@"
* **Profil Kustom `motorcycle.lua`:**
* **Why:** OSRM tidak menyediakan profil motor secara default. Konfigurasi ini dibuat untuk meniru perilaku pengendara motor di Indonesia.
* **What it does:**
1. **`require('car')`**: Menggunakan profil mobil sebagai dasar, jadi kita tidak perlu mendefinisikan ulang semua kecepatan jalan dari awal.
1. **`require('car')`**: Menggunakan profil mobil sebagai dasar, jadi proses ini tidak perlu mendefinisikan ulang semua kecepatan jalan dari awal.
2. **`restrictions`**: Bagian terpenting. Ini secara eksplisit melarang motor memasuki jalan tol (`highway:motorway`), jalan khusus mobil (`motorcar:yes`), dan jalan berbayar (`toll`). Aturan ini didasarkan pada tag OpenStreetMap.
3. **`properties`**: Sedikit mengubah parameter seperti penalti putar balik (`u_turn_penalty`) dan kecepatan maksimum (`max_speed`).
......
......@@ -202,12 +202,3 @@ jupyterlab -d /home/user/projects -p 9999
* [Jupyter Lab Documentation](https://jupyterlab.readthedocs.io/en/stable/)
* [Miniconda Installation](https://docs.conda.io/en/latest/miniconda.html)
---
**Dokumentasi ini self-contained**, mencakup semua langkah dari setup Conda/Mamba sampai wrapper script untuk Jupyter Lab.
---
Kalau mau, aku bisa buat **versi PDF siap cetak** atau **Markdown lengkap dengan snippet copy-paste**, supaya bisa langsung dibagikan ke tim.
Kamu mau aku buatkan versi PDF/Markdown itu juga?
......@@ -383,6 +383,3 @@ flowchart TD
| Domain/API structure | ✅ Confirmed |
| Mermaid workflow | ✅ Included |
---
Apakah kamu ingin saya jadikan **dokumen `.md` (Markdown)** dari daftar di atas, agar bisa langsung digunakan sebagai **AI-prompt atau dokumentasi teknis proyek**?
......@@ -2,18 +2,18 @@
### Tahap 1: Persiapan dan Pemahaman Konteks
Sebelum kita melangkah lebih jauh ke konfigurasi teknis, penting untuk memahami mengapa hardening SSH itu krusial dan apa saja yang perlu dipersiapkan.
Sebelum proses ini melangkah lebih jauh ke konfigurasi teknis, penting untuk memahami mengapa hardening SSH itu krusial dan apa saja yang perlu dipersiapkan.
#### Mengapa Hardening SSH Penting?
SSH (Secure Shell) adalah protokol jaringan yang memungkinkan kita untuk mengakses dan mengelola server secara aman melalui saluran terenkripsi. Karena SSH adalah pintu gerbang utama ke server, menjaganya tetap aman adalah prioritas utama. Hardening SSH adalah serangkaian langkah untuk memperkuat konfigurasi default SSH, mengurangi potensi kerentanan, dan melindungi server dari serangan seperti:
SSH (Secure Shell) adalah protokol jaringan yang memungkinkan proses ini untuk mengakses dan mengelola server secara aman melalui saluran terenkripsi. Karena SSH adalah pintu gerbang utama ke server, menjaganya tetap aman adalah prioritas utama. Hardening SSH adalah serangkaian langkah untuk memperkuat konfigurasi default SSH, mengurangi potensi kerentanan, dan melindungi server dari serangan seperti:
1. **Serangan Brute-Force:** Upaya mencoba berbagai kombinasi kata sandi untuk masuk ke sistem.
2. **Serangan Man-in-the-Middle (MITM):** Penyerang mencegat komunikasi antara klien dan server.
3. **Akses Tidak Sah:** Pengguna yang tidak berwenang mendapatkan akses ke server.
4. **Eskalasi Hak Istimewa:** Penyerang mendapatkan kontrol lebih tinggi dari yang seharusnya.
Dengan hardening SSH, kita bertujuan untuk mengurangi "permukaan serangan" (attack surface) server.
Dengan hardening SSH, proses ini bertujuan untuk mengurangi "permukaan serangan" (attack surface) server.
#### Prasyarat dan Asumsi
......@@ -28,27 +28,27 @@ Sebelum melanjutkan, pastikan memiliki hal-hal berikut:
* **OpenSSH Server (`openssh-server`):** Ini adalah implementasi server SSH yang paling umum digunakan. Rocky Linux secara default menginstal ini.
* **OpenSSH Client (`openssh-client`):** Digunakan untuk terhubung ke server SSH.
* **`sshd_config`:** File konfigurasi utama untuk server OpenSSH. Kita akan banyak berinteraksi dengan file ini.
* **`sshd_config`:** File konfigurasi utama untuk server OpenSSH. proses ini akan banyak berinteraksi dengan file ini.
* **`firewalld`:** Firewall default di Rocky Linux, akan digunakan untuk mengelola akses port SSH.
* **`auditd` (Opsional, tapi direkomendasikan):** Untuk logging aktivitas dan keamanan sistem.
#### Struktur File Konfigurasi SSH
File konfigurasi utama yang akan kita ubah terletak di:
File konfigurasi utama yang akan proses ini ubah terletak di:
* `/etc/ssh/sshd_config`: Ini adalah file konfigurasi global untuk daemon SSH (sshd). Perubahan yang dilakukan di sini akan mempengaruhi semua koneksi SSH.
* `/etc/ssh/ssh_config`: Ini adalah file konfigurasi klien SSH. Meskipun bukan fokus utama hardening server, penting untuk diketahui.
* `~/.ssh/`: Direktori ini (di direktori home setiap pengguna) berisi kunci SSH pribadi (`id_rsa`, `id_ed25519`) dan kunci publik yang diizinkan (`authorized_keys`).
**Kapan** kita akan melakukan hardening ini? **Sekarang**, sebelum server diekspos ke lingkungan produksi atau bahkan jika sudah berjalan, ini adalah langkah keamanan yang mendesak.
**Kapan** proses ini akan melakukan hardening ini? **Sekarang**, sebelum server diekspos ke lingkungan produksi atau bahkan jika sudah berjalan, ini adalah langkah keamanan yang mendesak.
**Siapa** yang harus melakukan ini? **Administrator sistem** atau siapa pun yang bertanggung jawab atas keamanan server.
**Di mana** konfigurasi ini diterapkan? **Di sisi server**, pada setiap server Rocky Linux 10 yang ingin amankan.
**Bagaimana** cara kerjanya? Kita akan memodifikasi parameter-parameter di `sshd_config` untuk membatasi akses, menguatkan autentikasi, dan mengurangi risiko eksploitasi.
**Bagaimana** cara kerjanya? proses ini akan memodifikasi parameter-parameter di `sshd_config` untuk membatasi akses, menguatkan autentikasi, dan mengurangi risiko eksploitasi.
**Mengapa** kita akan menggunakan pendekatan bertahap? Karena perubahan konfigurasi SSH dapat berisiko mengunci dari server jika tidak dilakukan dengan hati-hati. Pendekatan bertahap memungkinkan kita untuk memverifikasi setiap perubahan.
**Mengapa** proses ini akan menggunakan pendekatan bertahap? Karena perubahan konfigurasi SSH dapat berisiko mengunci dari server jika tidak dilakukan dengan hati-hati. Pendekatan bertahap memungkinkan proses ini untuk memverifikasi setiap perubahan.
---
......@@ -63,7 +63,7 @@ Sebelum melakukan perubahan apa pun pada konfigurasi SSH, langkah paling krusial
* **Titik Pemulihan (Rollback Point):** Memberikan "undo button" jika perubahan yang lakukan tidak berjalan sesuai harapan.
* **Analisis Perubahan:** Memungkinkan untuk membandingkan konfigurasi sebelum dan sesudah perubahan.
#### Apa yang Akan Kita Backup?
#### Apa yang Akan proses ini Backup?
File utama yang perlu di-backup adalah `/etc/ssh/sshd_config`. Ini adalah file konfigurasi daemon SSH server.
......@@ -151,15 +151,15 @@ Salah satu langkah pertama dan paling efektif dalam hardening SSH adalah menguba
#### Port yang Direkomendasikan
Pilih port di atas 1024, dan sebaiknya di atas 10.000, untuk menghindari konflik dengan layanan sistem lainnya yang sudah menggunakan port rendah (well-known ports). Pastikan port yang pilih tidak digunakan oleh layanan lain yang berjalan di server. Contoh port yang bisa digunakan: 2222, 22222, 33000, 50000. Untuk contoh ini, kita akan menggunakan **Port 22222**.
Pilih port di atas 1024, dan sebaiknya di atas 10.000, untuk menghindari konflik dengan layanan sistem lainnya yang sudah menggunakan port rendah (well-known ports). Pastikan port yang pilih tidak digunakan oleh layanan lain yang berjalan di server. Contoh port yang bisa digunakan: 2222, 22222, 33000, 50000. Untuk contoh ini, proses ini akan menggunakan **Port 22222**.
#### Langkah-langkah Mengubah Port SSH
Kita akan melakukan ini dalam dua langkah utama: memodifikasi `sshd_config` dan memperbarui konfigurasi `firewalld`.
proses ini akan melakukan ini dalam dua langkah utama: memodifikasi `sshd_config` dan memperbarui konfigurasi `firewalld`.
**1. Memodifikasi File Konfigurasi SSH (`sshd_config`)**
Kita akan mengedit file `/etc/ssh/sshd_config` menggunakan editor teks seperti `nano` atau `vi`. Saya akan menggunakan `vi` dalam contoh ini, tetapi bebas menggunakan editor pilihan.
proses ini akan mengedit file `/etc/ssh/sshd_config` menggunakan editor teks seperti `nano` atau `vi`. Perlu menggunakan `vi` dalam contoh ini, tetapi bebas menggunakan editor pilihan.
```bash
sudo vi /etc/ssh/sshd_config
......@@ -342,7 +342,7 @@ The key's randomart image is:
Setelah selesai, akan memiliki dua file di direktori `~/.ssh/`:
* `id_ed25519`: Kunci privat (HARUS DIJAGA KERAHASIAANNYA).
* `id_ed25519.pub`: Kunci publik (yang akan kita letakkan di server).
* `id_ed25519.pub`: Kunci publik (yang akan proses ini letakkan di server).
**2. Salin Kunci Publik ke Server**
......@@ -356,7 +356,7 @@ ssh-copy-id -i ~/.ssh/id_ed25519.pub -p 22222 <nama_pengguna>@<alamat_ip_server>
* `ssh-copy-id`: Skrip yang menyalin kunci publik ke server remote dan menambahkannya ke file `~/.ssh/authorized_keys` di server. Ini juga mengatur izin file yang benar.
* `-i ~/.ssh/id_ed25519.pub`: Menentukan lokasi kunci publik yang akan disalin.
* `-p 22222`: Menentukan port SSH server (port baru yang sudah kita konfigurasikan di Tahap 3).
* `-p 22222`: Menentukan port SSH server (port baru yang sudah proses ini konfigurasikan di Tahap 3).
* `<nama_pengguna>@<alamat_ip_server>`: Detail koneksi server.
**Contoh Output `ssh-copy-id`:**
......@@ -389,7 +389,7 @@ Jika diminta passphrase, masukkan passphrase kunci privat. Jika berhasil masuk t
### Bagian B: Mengkonfigurasi SSH Server untuk Hanya Mengizinkan Autentikasi Kunci
Sekarang setelah yakin bahwa dapat masuk ke server menggunakan SSH key, kita dapat mengkonfigurasi server untuk melarang autentikasi kata sandi. Lakukan ini **di server** dalam sesi SSH yang masih berjalan.
Sekarang setelah yakin bahwa dapat masuk ke server menggunakan SSH key, proses ini dapat mengkonfigurasi server untuk melarang autentikasi kata sandi. Lakukan ini **di server** dalam sesi SSH yang masih berjalan.
**1. Memodifikasi File Konfigurasi SSH (`sshd_config`)**
......@@ -499,7 +499,7 @@ sudo systemctl restart sshd
### Tahap 5: Melarang Login Root Langsung dan Membatasi Akses Pengguna
Setelah kita beralih ke autentikasi SSH key, langkah hardening berikutnya adalah mencegah login langsung sebagai pengguna `root` dan mengontrol siapa saja yang dapat mengakses SSH.
Setelah proses ini beralih ke autentikasi SSH key, langkah hardening berikutnya adalah mencegah login langsung sebagai pengguna `root` dan mengontrol siapa saja yang dapat mengakses SSH.
#### Mengapa Melarang Login Root Langsung?
......@@ -517,7 +517,7 @@ Setelah kita beralih ke autentikasi SSH key, langkah hardening berikutnya adalah
**1. Verifikasi Adanya Akun Pengguna Biasa dengan Hak `sudo`**
Sebelum melarang login root, **pastikan** memiliki setidaknya satu akun pengguna biasa yang:
* Sudah memiliki SSH key di server (seperti yang kita lakukan di Tahap 4).
* Sudah memiliki SSH key di server (seperti yang proses ini lakukan di Tahap 4).
* Memiliki hak istimewa `sudo` untuk melakukan perintah administratif.
dapat memeriksa apakah pengguna memiliki hak `sudo` dengan mencoba perintah `sudo`:
......@@ -555,7 +555,7 @@ Pastikan dapat login dengan `newuser` menggunakan SSH key sebelum melanjutkan.
**2. Melarang Login Root Langsung**
Kita akan memodifikasi file `/etc/ssh/sshd_config` lagi.
proses ini akan memodifikasi file `/etc/ssh/sshd_config` lagi.
```bash
sudo vi /etc/ssh/sshd_config
......@@ -565,7 +565,7 @@ Cari dan ubah parameter `PermitRootLogin`:
* **`PermitRootLogin no`**:
* **Definisi:** Parameter ini mengontrol apakah akun `root` dapat langsung login melalui SSH.
* **Nilai Default:** `prohibit-password` (artinya root bisa login dengan SSH key, tetapi tidak dengan kata sandi). Kita ingin membuatnya lebih ketat menjadi `no`.
* **Nilai Default:** `prohibit-password` (artinya root bisa login dengan SSH key, tetapi tidak dengan kata sandi). proses ini ingin membuatnya lebih ketat menjadi `no`.
* **Usecase:** Untuk mencegah penyerang langsung menargetkan akun `root`. Pengguna harus login sebagai pengguna biasa dan kemudian menggunakan `sudo` atau `su`.
* **Skenario:** Ketika ingin meningkatkan keamanan dengan menambahkan lapisan pertahanan ekstra terhadap akses `root` yang tidak sah.
......@@ -670,7 +670,7 @@ Langkah-langkah hardening ini bertujuan untuk mencegah sesi SSH yang tidak aktif
#### Langkah-langkah Penerapan
Kita akan memodifikasi file `/etc/ssh/sshd_config` lagi.
proses ini akan memodifikasi file `/etc/ssh/sshd_config` lagi.
```bash
sudo vi /etc/ssh/sshd_config
......@@ -779,24 +779,24 @@ Untuk memvalidasi `MaxAuthTries` dan `MaxStartups`:
### Tahap 7: Mengkonfigurasi Protokol, Ciphers, MACs, dan KexAlgorithms yang Kuat
Ini adalah langkah teknis yang penting dalam hardening SSH, di mana kita secara eksplisit menentukan algoritma kriptografi yang diizinkan untuk digunakan oleh server SSH. Dengan menghilangkan algoritma yang lebih tua atau yang dianggap lemah, kita memastikan bahwa semua komunikasi SSH dienkripsi dengan standar keamanan terbaik.
Ini adalah langkah teknis yang penting dalam hardening SSH, di mana proses ini secara eksplisit menentukan algoritma kriptografi yang diizinkan untuk digunakan oleh server SSH. Dengan menghilangkan algoritma yang lebih tua atau yang dianggap lemah, proses ini memastikan bahwa semua komunikasi SSH dienkripsi dengan standar keamanan terbaik.
#### Konteks: Protokol, Ciphers, MACs, dan KexAlgorithms
* **Protokol:** SSH memiliki dua versi utama, Protokol 1 (usang dan tidak aman) dan Protokol 2 (modern dan aman). Kita harus memastikan hanya Protokol 2 yang digunakan.
* **Protokol:** SSH memiliki dua versi utama, Protokol 1 (usang dan tidak aman) dan Protokol 2 (modern dan aman). proses ini harus memastikan hanya Protokol 2 yang digunakan.
* **Ciphers (Algoritma Enkripsi):** Digunakan untuk mengenkripsi data yang ditransfer antara klien dan server. Penting untuk menggunakan cipher yang kuat dan modern. Contoh: `aes256-gcm@openssh.com`, `chacha20-poly1305@openssh.com`.
* **MACs (Message Authentication Codes):** Digunakan untuk memastikan integritas data, yaitu bahwa data tidak diubah selama transmisi. Penting untuk menggunakan MAC yang kuat untuk mencegah serangan modifikasi data. Contoh: `hmac-sha2-512-etm@openssh.com`, `hmac-sha2-256-etm@openssh.com`.
* **KexAlgorithms (Key Exchange Algorithms):** Digunakan untuk pertukaran kunci kriptografi yang aman antara klien dan server. Algoritma ini memastikan bahwa kunci sesi yang akan digunakan untuk enkripsi data tidak dapat disadap. Contoh: `diffie-hellman-group14-sha256`, `curve25519-sha256`.
#### Mengapa Perlu Mengkonfigurasi Ini?
* **Mencegah Serangan Downgrade:** Penyerang mungkin mencoba memaksa koneksi SSH untuk menggunakan algoritma yang lebih lemah yang memiliki kerentanan yang diketahui. Dengan secara eksplisit mendefinisikan hanya algoritma yang kuat, kita mencegah hal ini.
* **Mencegah Serangan Downgrade:** Penyerang mungkin mencoba memaksa koneksi SSH untuk menggunakan algoritma yang lebih lemah yang memiliki kerentanan yang diketahui. Dengan secara eksplisit mendefinisikan hanya algoritma yang kuat, proses ini mencegah hal ini.
* **Melindungi Data Sensitif:** Memastikan bahwa data yang lewat di saluran SSH dilindungi dengan enkripsi yang sangat kuat, sehingga sulit untuk disadap atau dimodifikasi.
* **Kepatuhan Standar Keamanan:** Mengikuti praktik terbaik dan rekomendasi dari badan keamanan siber.
#### Langkah-langkah Penerapan
Kita akan memodifikasi file `/etc/ssh/sshd_config` lagi.
proses ini akan memodifikasi file `/etc/ssh/sshd_config` lagi.
```bash
sudo vi /etc/ssh/sshd_config
......@@ -933,7 +933,7 @@ Untuk memvalidasi bahwa server menggunakan algoritma yang tentukan, dapat menggu
### Tahap 8: Pengaturan Keamanan Tambahan dan Logging
Pada tahap ini, kita akan menerapkan beberapa pengaturan keamanan tambahan di `sshd_config` untuk membatasi fungsionalitas yang tidak perlu dan meningkatkan kemampuan audit melalui logging.
Pada tahap ini, proses ini akan menerapkan beberapa pengaturan keamanan tambahan di `sshd_config` untuk membatasi fungsionalitas yang tidak perlu dan meningkatkan kemampuan audit melalui logging.
#### Mengapa Pengaturan Tambahan Ini Penting?
......@@ -942,7 +942,7 @@ Pada tahap ini, kita akan menerapkan beberapa pengaturan keamanan tambahan di `s
#### Langkah-langkah Penerapan
Kita akan memodifikasi file `/etc/ssh/sshd_config` lagi.
proses ini akan memodifikasi file `/etc/ssh/sshd_config` lagi.
```bash
sudo vi /etc/ssh/sshd_config
......@@ -1070,11 +1070,11 @@ sudo systemctl restart sshd
### Tahap 9: Rangkuman Konfigurasi dan Persiapan Skrip Otomatisasi
Kita telah melalui banyak perubahan pada konfigurasi SSH. Pada tahap ini, kita akan merangkum semua perubahan yang telah kita lakukan pada file `/etc/ssh/sshd_config` dan mempersiapkan diri untuk membuat skrip bash yang dapat mengotomatisasi proses ini.
proses ini telah melalui banyak perubahan pada konfigurasi SSH. Pada tahap ini, proses ini akan merangkum semua perubahan yang telah proses ini lakukan pada file `/etc/ssh/sshd_config` dan mempersiapkan diri untuk membuat skrip bash yang dapat mengotomatisasi proses ini.
#### Rangkuman Konfigurasi `sshd_config` (Best Practice Hardened)
Berikut adalah ringkasan dari parameter-parameter yang direkomendasikan dan nilainya setelah semua langkah hardening yang kita lakukan:
Berikut adalah ringkasan dari parameter-parameter yang direkomendasikan dan nilainya setelah semua langkah hardening yang proses ini lakukan:
```ini
# --- General Settings ---
......@@ -1126,7 +1126,7 @@ Membuat skrip otomatisasi sangat berguna untuk menerapkan konfigurasi ini secara
* **Error dan Exception Handler:** Menangani kesalahan dengan baik dan memberikan pesan yang informatif.
* **Verbose Message:** Memberikan umpan balik yang jelas tentang apa yang sedang dilakukan skrip.
**Struktur Skrip yang Akan Kita Bangun:**
**Struktur Skrip yang Akan proses ini Bangun:**
1. **Validasi Lingkungan:** Memeriksa apakah skrip dijalankan sebagai root dan di sistem operasi yang didukung (Rocky Linux 10).
2. **Parsing Argumen:** Mengambil input dari pengguna untuk port SSH, pengguna/grup yang diizinkan, dan mode dry-run.
......@@ -1136,13 +1136,11 @@ Membuat skrip otomatisasi sangat berguna untuk menerapkan konfigurasi ini secara
6. **Fungsi Restart Layanan:** Me-restart daemon SSH.
7. **Fungsi Verifikasi:** Memverifikasi bahwa SSH berfungsi setelah perubahan.
Saya akan menyajikan skrip bash lengkap pada tahap berikutnya. Skrip ini akan mencakup semua praktik terbaik yang telah kita bahas.
---
### Tahap 10: Full Bash Script untuk Otomatisasi Hardening SSH
Skrip bash berikut akan mengimplementasikan semua langkah hardening SSH yang telah kita bahas. Skrip ini dirancang agar modular, parameter, memiliki mode dry-run, dan penanganan kesalahan yang kuat.
Skrip bash berikut akan mengimplementasikan semua langkah hardening SSH yang telah proses ini bahas. Skrip ini dirancang agar modular, parameter, memiliki mode dry-run, dan penanganan kesalahan yang kuat.
**Penting Sebelum Menjalankan Skrip:**
......@@ -1201,7 +1199,7 @@ Skrip bash berikut akan mengimplementasikan semua langkah hardening SSH yang tel
SSH_CONFIG="/etc/ssh/sshd_config"
SSH_BAK_DIR="/etc/ssh/sshd_config.bak"
FIREWALLD_ZONE="public"
DEFAULT_SSH_PORT=22222 # Port SSH default yang akan kita gunakan
DEFAULT_SSH_PORT=22222 # Port SSH default yang akan proses ini gunakan
DRY_RUN=false
NEW_SSH_PORT=""
ALLOW_USERS_LIST=""
......
### Tahap 1: Pemahaman Konteks Fail2Ban dan Persiapan
Sebelum kita masuk ke instalasi dan konfigurasi, mari kita pahami apa itu Fail2Ban, mengapa ia penting, dan apa saja yang perlu dipersiapkan.
Sebelum proses ini masuk ke instalasi dan konfigurasi, mari proses ini pahami apa itu Fail2Ban, mengapa ia penting, dan apa saja yang perlu dipersiapkan.
#### Apa Itu Fail2Ban?
......@@ -9,7 +9,7 @@ Fail2Ban adalah sebuah framework pencegah intrusi berbasis log yang memindai fil
#### Mengapa Fail2Ban Penting untuk Hardening SSH?
Meskipun kita sudah melakukan banyak langkah hardening SSH (mengubah port, SSH Key, dll.), Fail2Ban menambahkan lapisan keamanan yang proaktif dan reaktif:
Meskipun proses ini sudah melakukan banyak langkah hardening SSH (mengubah port, SSH Key, dll.), Fail2Ban menambahkan lapisan keamanan yang proaktif dan reaktif:
1. **Pertahanan Reaktif Terhadap Brute-Force:** Ini adalah fungsi utamanya. Jika ada penyerang yang mencoba SSH key yang berbeda-beda, atau jika ada port scanner yang menemukan port SSH baru dan mencoba brute-force, Fail2Ban akan mendeteksi upaya login yang gagal dan secara otomatis memblokir IP tersebut.
2. **Mengurangi Beban Server:** Dengan memblokir penyerang sejak dini, mengurangi beban pada server karena upaya autentikasi yang berulang tidak akan sampai ke daemon SSH lagi.
......@@ -27,8 +27,8 @@ Meskipun kita sudah melakukan banyak langkah hardening SSH (mengubah port, SSH K
1. **Rocky Linux 10:** Sistem operasi target.
2. **Akses Root atau `sudo`:** Diperlukan untuk instalasi dan konfigurasi.
3. **`firewalld` Aktif dan Berjalan:** Fail2Ban akan berinteraksi dengan `firewalld` untuk menerapkan blokir IP. Pastikan `firewalld` sudah terinstal dan berjalan (seperti yang kita konfigurasikan di tahap hardening SSH sebelumnya).
4. **Port SSH Kustom:** Asumsi bahwa sudah mengubah port SSH default (misalnya ke 22222) seperti yang kita lakukan di tutorial sebelumnya. Fail2Ban akan dikonfigurasi untuk memantau port ini.
3. **`firewalld` Aktif dan Berjalan:** Fail2Ban akan berinteraksi dengan `firewalld` untuk menerapkan blokir IP. Pastikan `firewalld` sudah terinstal dan berjalan (seperti yang proses ini konfigurasikan di tahap hardening SSH sebelumnya).
4. **Port SSH Kustom:** Asumsi bahwa sudah mengubah port SSH default (misalnya ke 22222) seperti yang proses ini lakukan di tutorial sebelumnya. Fail2Ban akan dikonfigurasi untuk memantau port ini.
5. **SSH Server Berjalan:** Daemon OpenSSH (`sshd`) harus berjalan dan aktif agar Fail2Ban dapat memantau log-nya.
#### Arsitektur Fail2Ban (Dependency & Use Case)
......@@ -53,11 +53,11 @@ Seorang penyerang mencoba login SSH ke server pada port 22222 dengan pengguna `a
### Tahap 2: Instalasi Fail2Ban
Pada tahap ini, kita akan menginstal paket Fail2Ban dari repositori default Rocky Linux 10.
Pada tahap ini, proses ini akan menginstal paket Fail2Ban dari repositori default Rocky Linux 10.
#### Mengapa Perlu Menginstal Fail2Ban?
Fail2Ban bukanlah bagian dari instalasi minimal Rocky Linux secara default. Oleh karena itu, kita perlu menginstalnya secara manual agar fungsionalitas pencegahan intrusi berbasis log ini dapat berjalan di server kita.
Fail2Ban bukanlah bagian dari instalasi minimal Rocky Linux secara default. Oleh karena itu, proses ini perlu menginstalnya secara manual agar fungsionalitas pencegahan intrusi berbasis log ini dapat berjalan di server.
#### Cara Menginstal Fail2Ban
......@@ -160,7 +160,7 @@ Jika melihat output versi seperti di atas, artinya instalasi berhasil.
**3. Aktifkan dan Mulai Layanan Fail2Ban**
Setelah instalasi, kita perlu mengaktifkan layanan Fail2Ban agar secara otomatis berjalan saat sistem booting dan memulainya sekarang.
Setelah instalasi, proses ini perlu mengaktifkan layanan Fail2Ban agar secara otomatis berjalan saat sistem booting dan memulainya sekarang.
```bash
sudo systemctl enable fail2ban
......@@ -200,7 +200,7 @@ Cari `Active: active (running)`. Jika melihat ini, layanan Fail2Ban berjalan den
### Tahap 3: Konfigurasi Fail2Ban (Jail dan Filter)
Pada tahap ini, kita akan mengkonfigurasi Fail2Ban untuk memantau upaya login SSH yang gagal di port kustom. Fail2Ban menggunakan konsep "jail" untuk menentukan layanan mana yang akan dimonitor dan bagaimana cara menangani insiden.
Pada tahap ini, proses ini akan mengkonfigurasi Fail2Ban untuk memantau upaya login SSH yang gagal di port kustom. Fail2Ban menggunakan konsep "jail" untuk menentukan layanan mana yang akan dimonitor dan bagaimana cara menangani insiden.
#### Struktur Konfigurasi Fail2Ban
......@@ -211,17 +211,17 @@ Urutan prioritas konfigurasi adalah:
2. `/etc/fail2ban/jail.d/*.conf` (konfigurasi kustom, menimpa `jail.conf`)
3. `/etc/fail2ban/jail.local` (konfigurasi kustom, menimpa `jail.conf` dan `jail.d/` jika konflik)
Kita akan membuat file konfigurasi baru di `/etc/fail2ban/jail.d/` untuk jail SSH kita.
proses ini akan membuat file konfigurasi baru di `/etc/fail2ban/jail.d/` untuk jail SSH.
#### Mengapa Konfigurasi Khusus Diperlukan?
* **Port Kustom:** Konfigurasi default Fail2Ban untuk SSH memantau port 22. Karena kita telah mengubah port SSH (misalnya ke 22222), kita perlu memberi tahu Fail2Ban untuk memantau port yang benar.
* **Port Kustom:** Konfigurasi default Fail2Ban untuk SSH memantau port 22. Karena proses ini telah mengubah port SSH (misalnya ke 22222), proses ini perlu memberi tahu Fail2Ban untuk memantau port yang benar.
* **Best Practice:** Menggunakan file `.local` atau `.d/` memastikan konfigurasi kustom tetap utuh saat Fail2Ban di-upgrade.
* **Fleksibilitas:** Memungkinkan penyesuaian parameter banning (seperti durasi ban, jumlah percobaan gagal) sesuai kebutuhan keamanan spesifik.
#### Parameter Konfigurasi Kunci
Berikut adalah parameter utama yang akan kita konfigurasikan:
Berikut adalah parameter utama yang akan proses ini konfigurasikan:
* **`ignoreip`**: Daftar alamat IP atau subnet yang akan diabaikan oleh Fail2Ban. Masukkan IP sendiri di sini agar tidak terkunci secara tidak sengaja.
* **`bantime`**: Durasi (dalam detik) IP akan diblokir. Default: 10 menit (600 detik).
......@@ -236,7 +236,7 @@ Berikut adalah parameter utama yang akan kita konfigurasikan:
**1. Buat File Konfigurasi Jail Kustom untuk SSH**
Kita akan membuat file `/etc/fail2ban/jail.d/ssh_hardening.conf`.
proses ini akan membuat file `/etc/fail2ban/jail.d/ssh_hardening.conf`.
```bash
sudo vi /etc/fail2ban/jail.d/ssh_hardening.conf
......@@ -272,7 +272,7 @@ ignoreip = 127.0.0.1/8 ::1 your_ip_address_or_subnet # Ganti ini!
action = %(action_)s
```
**Penjelasan Parameter Kunci dalam Konteks Kita:**
**Penjelasan Parameter Kunci dalam Konteks:**
* **`[sshd]`**: Ini mendefinisikan sebuah "jail" bernama `sshd`. Fail2Ban akan memantau layanan ini.
* **`enabled = true`**: Mengaktifkan jail ini.
......@@ -369,11 +369,11 @@ Setelah `bantime` berakhir, IP secara otomatis akan di-unban, dan bisa mencoba l
### Tahap 4: Rangkuman Konfigurasi Fail2Ban dan Full Bash Script untuk Otomatisasi
Kita telah menginstal dan mengkonfigurasi Fail2Ban secara manual. Sekarang, mari kita rangkum konfigurasi dan kemudian membuat skrip bash untuk mengotomatisasi proses ini, yang dapat digunakan untuk penerapan yang konsisten dan cepat.
proses ini telah menginstal dan mengkonfigurasi Fail2Ban secara manual. Sekarang, mari proses ini rangkum konfigurasi dan kemudian membuat skrip bash untuk mengotomatisasi proses ini, yang dapat digunakan untuk penerapan yang konsisten dan cepat.
#### Rangkuman Konfigurasi Fail2Ban (Best Practice)
Berikut adalah ringkasan dari konfigurasi Fail2Ban untuk SSH yang kita telah buat di `/etc/fail2ban/jail.d/ssh_hardening.conf`:
Berikut adalah ringkasan dari konfigurasi Fail2Ban untuk SSH yang proses ini telah buat di `/etc/fail2ban/jail.d/ssh_hardening.conf`:
```ini
# ==============================================================================
......
#!/bin/bash
# ==================================================================================================
# install-ngpm.sh - Skrip Otomatis untuk Instalasi Nginx Proxy Manager (NGPM)
# ==================================================================================================
# Author: AI Solutions Architect
# Version: 2.3.0 (Adaptive Output Formatting)
# Target OS: Rocky Linux 10 (and RHEL-compatibles)
# Environment: Docker Rootless for non-root user
#
# Description:
# Skrip ini mengotomatiskan seluruh proses deployment Nginx Proxy Manager menggunakan
# Docker Compose dalam lingkungan rootless, dengan fokus pada keandalan, keamanan, dan
# pengalaman pengguna yang superior.
#
# Perubahan v2.3.0:
# - UX (Major): Implementasi pemformatan output yang adaptif pada fungsi 'execute_cmd'.
# - Jika output hanya satu baris, ditampilkan secara ringkas (e.g., "| Output: Success").
# - Jika output multi-baris, ditampilkan dalam format blok yang rapi untuk keterbacaan.
# - UX (Minor): Output "success" dari firewall-cmd diubah menjadi "Success" untuk estetika.
# - ROBUSTNESS: Mengintegrasikan semua perbaikan sebelumnya, termasuk pengecekan sysctl.
# ==================================================================================================
# --- Konfigurasi Keamanan Shell ---
set -euo pipefail
# --- Variabel Global dan Nilai Default ---
PROJECT_DIR="${HOME}/data/docker-data/ngpm"
DOCKER_NETWORK="ngpm-network"
APP_CONTAINER_NAME="ngpm-app"
DB_CONTAINER_NAME="ngpm-db"
ADMIN_PORT="81"
HTTP_PORT="80"
HTTPS_PORT="443"
DB_NGPM_NAME="ngpm"
DB_NGPM_USER="ngpm-user"
# --- Variabel Status Skrip ---
DRY_RUN=false
ADMIN_SOURCE_IP=""
# --- Kode Warna untuk Logging ---
readonly C_RESET='\033[0m'
readonly C_RED='\033[0;31m'
readonly C_GREEN='\033[0;32m'
readonly C_YELLOW='\033[0;33m'
readonly C_BLUE='\033[0;34m'
readonly C_CYAN='\033[0;36m'
readonly C_BOLD='\033[1m'
# ==============================================================================
# FUNGSI-FUNGSI BANTUAN (HELPER FUNCTIONS)
# ==============================================================================
log() { local c="$1"; local t="$2"; local m="$3"; echo -e "$(date '+%Y-%m-%d %H:%M:%S') ${c}${C_BOLD}[${t}]${C_RESET} ${m}"; }
log_info() { log "${C_BLUE}" "INFO" "$1"; }
log_success() { log "${C_GREEN}" "SUCCESS" "$1"; }
log_warn() { log "${C_YELLOW}" "WARN" "$1"; }
log_error() { log "${C_RED}" "ERROR" "$1"; }
# IMPROVED v2.3.0: Fungsi eksekusi dengan format output adaptif.
execute_cmd() {
log_info "Executing command: ${C_CYAN}$*${C_RESET}"
if [ "$DRY_RUN" = true ]; then
log_warn "[DRY RUN] Perintah di atas disimulasikan dan tidak akan dieksekusi."
echo
return 0
fi
# Eksekusi perintah dan tangkap output serta error stream
# Menggunakan 'eval' untuk menangani perintah dengan pipe (seperti pada sysctl)
if output=$(eval "$@" 2>&1); then
# Hanya proses jika ada output
if [ -n "$output" ]; then
# Kosmetik: Ubah "success" menjadi "Success"
if [[ "$output" == "success" ]]; then output="Success"; fi
# Hitung jumlah baris pada output
local line_count
line_count=$(wc -l <<< "$output")
if [ "$line_count" -eq 1 ]; then
# Format ringkas untuk output satu baris
echo -e "${C_CYAN} | Output:${C_RESET} ${output}"
else
# Format blok untuk output multi-baris
echo -e "${C_CYAN} | Output:${C_RESET}"
echo "$output" | sed "s/^/ | /; s/\r//g"
fi
fi
echo
else
local exit_code=$?
echo
log_error "Perintah gagal dengan kode keluar ${exit_code}."
if [ -n "$output" ]; then
echo -e "${C_RED} | Error Output:${C_RESET}"
echo "$output" | sed "s/^/ | /; s/\r//g"
fi
exit "$exit_code"
fi
}
command_exists() { command -v "$1" >/dev/null 2>&1; }
show_help() {
cat << 'EOF'
${C_BOLD}Skrip Otomatis untuk Instalasi Nginx Proxy Manager (NGPM)${C_RESET}
Versi 2.3.0
Skrip ini mengotomatiskan deployment NGPM menggunakan Docker Compose dalam mode rootless,
dengan fokus pada keandalan, keamanan, dan pengalaman pengguna.
${C_BOLD}PENGGUNAAN:${C_RESET}
./install-ngpm.sh [OPTIONS]
${C_BOLD}OPTIONS:${C_RESET}
--project-dir <path> Direktori kerja utama untuk data NGPM.
(Default: "${HOME}/data/docker-data/ngpm")
--network-name <name> Nama jaringan internal Docker. (Default: "ngpm-network")
--app-name <name> Nama kontainer aplikasi NGPM. (Default: "ngpm-app")
--db-name <name> Nama kontainer basis data. (Default: "ngpm-db")
--admin-port <port> Port host untuk antarmuka admin. (Default: 81)
--http-port <port> Port host untuk trafik HTTP. (Default: 80)
--https-port <port> Port host untuk trafik HTTPS. (Default: 443)
--db-database <name> Nama basis data internal. (Default: "ngpm")
--db-user <name> Nama pengguna basis data. (Default: "ngpm-user")
--allow-admin-from <ip/cidr> (Sangat Direkomendasikan) Batasi akses admin dari IP/CIDR ini.
--dry-run Jalankan dalam mode simulasi, tidak ada perubahan yang diterapkan.
--help Tampilkan pesan bantuan ini.
EOF
}
# ==============================================================================
# FUNGSI-FUNGSI LOGIKA UTAMA (MAIN LOGIC FUNCTIONS)
# ==============================================================================
check_and_configure_sysctl() {
log_info "Memeriksa konfigurasi sysctl untuk binding port non-root..."
local min_port; min_port=$(printf "%s\n" "$HTTP_PORT" "$HTTPS_PORT" "$ADMIN_PORT" | sort -n | head -n1)
local current_limit; current_limit=$(sysctl -n net.ipv4.ip_unprivileged_port_start)
if [[ "$current_limit" -le "$min_port" ]]; then
log_success "Konfigurasi sysctl 'net.ipv4.ip_unprivileged_port_start' (${current_limit}) sudah memadai."
echo
return
fi
log_warn "Terdeteksi potensi masalah: Batas port non-root (${current_limit}) lebih tinggi dari port yang dibutuhkan (${min_port})."
log_warn "Ini akan menyebabkan error 'permission denied' saat menjalankan kontainer rootless."
echo
if [ "$DRY_RUN" = true ]; then
log_info "[DRY RUN] Skrip AKAN menyarankan pembuatan file /etc/sysctl.d/99-rootless-ports.conf dengan isi:"
echo -e "${C_CYAN} | net.ipv4.ip_unprivileged_port_start=${min_port}${C_RESET}"
log_info "[DRY RUN] Dan AKAN menjalankan 'sudo sysctl --system'."
echo
return
fi
read -p "Apakah ingin skrip ini secara otomatis mengkonfigurasinya untuk? (y/N): " -r choice
echo
if [[ ! "$choice" =~ ^[Yy]$ ]]; then
log_error "Aksi dibatalkan oleh pengguna. Mohon konfigurasikan sysctl secara manual untuk melanjutkan."
log_info "Contoh: echo 'net.ipv4.ip_unprivileged_port_start=${min_port}' | sudo tee /etc/sysctl.d/99-rootless-ports.conf && sudo sysctl --system"
exit 1
fi
local sysctl_conf="/etc/sysctl.d/99-rootless-ports.conf"
log_info "Membuat file konfigurasi sysctl di ${sysctl_conf}... (memerlukan sudo)"
execute_cmd "echo 'net.ipv4.ip_unprivileged_port_start=${min_port}' | sudo tee '${sysctl_conf}' > /dev/null"
log_info "Menerapkan konfigurasi sysctl baru..."
execute_cmd "sudo sysctl --system"
log_success "Konfigurasi sysctl berhasil diperbarui."
echo
}
preflight_checks() {
log_info "Memulai Pengecekan Pra-Instalasi (Pre-flight Checks)..."
if [ "$(id -u)" -eq 0 ]; then log_error "Skrip ini dirancang untuk Docker rootless. Mohon jangan dijalankan sebagai user 'root'."; exit 1; fi
local dependencies=("docker" "sudo" "firewall-cmd" "openssl" "sysctl"); for cmd in "${dependencies[@]}"; do if ! command_exists "$cmd"; then log_error "Dependensi krusial tidak ditemukan: '${cmd}'."; exit 1; fi; done
if ! docker info &>/dev/null; then log_error "Tidak dapat terhubung ke Docker daemon."; log_warn "Coba jalankan: systemctl --user start docker"; exit 1; fi
if ! docker compose version &>/dev/null; then log_error "Perintah 'docker compose' (v2) tidak ditemukan."; exit 1; fi
log_info "Memverifikasi dan menyegarkan tiket sudo untuk menghindari prompt di tengah jalan..."
if ! sudo -v; then log_error "Gagal mendapatkan hak akses sudo."; exit 1; fi
log_success "Tiket sudo berhasil diverifikasi."
echo
check_and_configure_sysctl
log_success "Semua pengecekan pra-instalasi berhasil."
echo
}
setup_environment() {
log_info "Menyiapkan struktur direktori dan file konfigurasi..."
local resolved_project_dir; resolved_project_dir=$(eval echo "${PROJECT_DIR}")
execute_cmd mkdir -p "${resolved_project_dir}"
local compose_file="${resolved_project_dir}/docker-compose.yml"; local env_file="${resolved_project_dir}/.env"
if [ -f "$compose_file" ] || [ -f "$env_file" ]; then
log_warn "File konfigurasi sudah ada di ${resolved_project_dir}. Melewati tahap pembuatan."
echo
return
fi
log_info "Menghasilkan password basis data yang kuat..."
local db_password; db_password=$(openssl rand -base64 32)
log_info "Mempersiapkan konten untuk file .env..."
local env_content; env_content=$(cat <<EOF
# =======================================================
# File Environment untuk Nginx Proxy Manager
# Dihasilkan secara otomatis oleh install-ngpm.sh
# Waktu: $(date)
# =======================================================
# --- Koneksi Basis Data ---
DB_MYSQL_HOST=${DB_CONTAINER_NAME}
DB_MYSQL_DATABASE=${DB_NGPM_NAME}
DB_MYSQL_USER=${DB_NGPM_USER}
DB_MYSQL_PASSWORD=${db_password}
EOF
)
log_info "Mempersiapkan konten untuk file docker-compose.yml..."
local compose_content; compose_content=$(cat <<EOF
# Definisi Stack Docker Compose untuk Nginx Proxy Manager
# Dihasilkan secara otomatis oleh install-ngpm.sh
services:
app:
image: jc21/nginx-proxy-manager:latest
container_name: ${APP_CONTAINER_NAME}
restart: unless-stopped
ports:
- "${HTTP_PORT}:80"
- "${HTTPS_PORT}:443"
- "${ADMIN_PORT}:81"
env_file:
- .env
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
depends_on:
db:
condition: service_healthy
networks:
- ${DOCKER_NETWORK}
db:
image: jc21/mariadb-aria:latest
container_name: ${DB_CONTAINER_NAME}
restart: unless-stopped
env_file:
- .env
volumes:
- ./data/mysql:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
timeout: 20s
retries: 10
networks:
- ${DOCKER_NETWORK}
networks:
${DOCKER_NETWORK}:
name: ${DOCKER_NETWORK}
EOF
)
if [ "$DRY_RUN" = true ]; then
log_info "[DRY RUN] Konten yang AKAN ditulis ke '${env_file}':"
echo -e "${C_CYAN}--- BEGIN .env ---${C_RESET}"; echo "${env_content}"; echo -e "${C_CYAN}--- END .env ---${C_RESET}\n"
log_info "[DRY RUN] Konten yang AKAN ditulis ke '${compose_file}':"
echo -e "${C_CYAN}--- BEGIN docker-compose.yml ---${C_RESET}"; echo "${compose_content}"; echo -e "${C_CYAN}--- END docker-compose.yml ---${C_RESET}\n"
else
log_info "Menulis file .env..."; echo "${env_content}" > "${env_file}"
log_info "Menulis file docker-compose.yml..."; echo "${compose_content}" > "${compose_file}"
log_success "File konfigurasi berhasil dibuat di ${resolved_project_dir}."
echo
fi
}
configure_firewall() {
log_info "Mengkonfigurasi aturan firewalld..."
local needs_reload=false
# HTTP
if [[ "${HTTP_PORT}" != "80" ]]; then if ! sudo firewall-cmd --permanent --query-port="${HTTP_PORT}/tcp" &>/dev/null; then execute_cmd sudo firewall-cmd --permanent --add-port="${HTTP_PORT}/tcp"; needs_reload=true; fi
else if ! sudo firewall-cmd --permanent --query-service="http" &>/dev/null; then execute_cmd sudo firewall-cmd --permanent --add-service="http"; needs_reload=true; fi; fi
# HTTPS
if [[ "${HTTPS_PORT}" != "443" ]]; then if ! sudo firewall-cmd --permanent --query-port="${HTTPS_PORT}/tcp" &>/dev/null; then execute_cmd sudo firewall-cmd --permanent --add-port="${HTTPS_PORT}/tcp"; needs_reload=true; fi
else if ! sudo firewall-cmd --permanent --query-service="https" &>/dev/null; then execute_cmd sudo firewall-cmd --permanent --add-service="https"; needs_reload=true; fi; fi
log_info "Mengkonfigurasi akses untuk port admin (${ADMIN_PORT}/tcp)..."
if [ -n "${ADMIN_SOURCE_IP}" ]; then
log_info "Menerapkan aturan keamanan: Membatasi akses HANYA dari ${ADMIN_SOURCE_IP}"
local rich_rule="rule family=\"ipv4\" source address=\"${ADMIN_SOURCE_IP}\" port port=\"${ADMIN_PORT}\" protocol=\"tcp\" accept"
if sudo firewall-cmd --permanent --query-port="${ADMIN_PORT}/tcp" &>/dev/null; then execute_cmd sudo firewall-cmd --permanent --remove-port="${ADMIN_PORT}/tcp"; needs_reload=true; fi
if ! sudo firewall-cmd --permanent --query-rich-rule="'${rich_rule}'" &>/dev/null; then execute_cmd sudo firewall-cmd --permanent --add-rich-rule="'${rich_rule}'"; needs_reload=true; fi
else
log_warn "Tidak ada batasan IP yang diberikan (--allow-admin-from). Port admin ${ADMIN_PORT}/tcp akan terbuka untuk umum."
log_warn "Ini tidak direkomendasikan untuk lingkungan produksi."
if ! sudo firewall-cmd --permanent --query-port="${ADMIN_PORT}/tcp" &>/dev/null; then execute_cmd sudo firewall-cmd --permanent --add-port="${ADMIN_PORT}/tcp"; needs_reload=true; fi
fi
if [ "$needs_reload" = true ]; then log_info "Menerapkan perubahan aturan firewall..."; execute_cmd sudo firewall-cmd --reload; else log_info "Konfigurasi firewall sudah sesuai, tidak ada perubahan yang diperlukan.\n"; fi
log_success "Firewall berhasil dikonfigurasi."
echo
}
launch_ngpm() {
log_info "Memulai stack kontainer Nginx Proxy Manager..."
local resolved_project_dir; resolved_project_dir=$(eval echo "${PROJECT_DIR}")
log_info "Berpindah ke direktori proyek: ${resolved_project_dir}"
if [ "$DRY_RUN" = false ]; then cd "${resolved_project_dir}"; else log_warn "[DRY RUN] Simulasi berpindah direktori ke ${resolved_project_dir}."; fi
echo
log_info "Menarik versi terbaru dari Docker images..."
execute_cmd docker compose pull
log_info "Memulai kontainer di background (detached mode)..."
execute_cmd docker compose up -d
log_success "Stack Nginx Proxy Manager telah berhasil dimulai."
echo
}
post_install_summary() {
log_info "Verifikasi status kontainer akhir..."
local resolved_project_dir; resolved_project_dir=$(eval echo "${PROJECT_DIR}")
if [ "$DRY_RUN" = false ]; then
cd "${resolved_project_dir}"; sleep 5; execute_cmd docker compose ps
else
log_warn "[DRY RUN] Simulasi verifikasi status dengan 'docker compose ps'."
echo
fi
local server_ip; server_ip=$(hostname -I | awk '{print $1}')
log_success "================= ${C_BOLD}INSTALASI SELESAI${C_RESET}${C_GREEN} ================="
log_info "sekarang dapat mengakses antarmuka web admin Nginx Proxy Manager di:"; log_info "URL: ${C_YELLOW}http://${server_ip}:${ADMIN_PORT}${C_RESET}"
if [ -n "${ADMIN_SOURCE_IP}" ]; then log_warn " (Akses hanya diizinkan dari alamat IP sumber: ${ADMIN_SOURCE_IP})"; fi
log_info "Gunakan kredensial default berikut untuk login pertama kali:"; log_info " Email: ${C_YELLOW}admin@example.com${C_RESET}"; log_info " Password: ${C_YELLOW}changeme${C_RESET}"
log_error "${C_BOLD}SANGAT PENTING:${C_RESET} Segera ubah email dan password default setelah berhasil login!"
log_success "=========================================================="
}
# ==============================================================================
# FUNGSI UTAMA (MAIN) & PARSING ARGUMEN
# ==============================================================================
main() {
while [[ $# -gt 0 ]]; do
case $1 in
--project-dir) PROJECT_DIR="$2"; shift 2 ;;
--network-name) DOCKER_NETWORK="$2"; shift 2 ;;
--app-name) APP_CONTAINER_NAME="$2"; shift 2 ;;
--db-name) DB_CONTAINER_NAME="$2"; shift 2 ;;
--admin-port) ADMIN_PORT="$2"; shift 2 ;;
--http-port) HTTP_PORT="$2"; shift 2 ;;
--https-port) HTTPS_PORT="$2"; shift 2 ;;
--db-database) DB_NGPM_NAME="$2"; shift 2 ;;
--db-user) DB_NGPM_USER="$2"; shift 2 ;;
--allow-admin-from) ADMIN_SOURCE_IP="$2"; shift 2 ;;
--dry-run) DRY_RUN=true; shift ;;
--help) show_help; exit 0 ;;
*) log_error "Argumen tidak dikenal: $1"; show_help; exit 1 ;;
esac
done
if [ "$DRY_RUN" = true ]; then log_warn "=========================================================="; log_warn "======= MENJALANKAN MODE DRY RUN ======="; log_warn "==========================================================\n"; fi
preflight_checks
setup_environment
configure_firewall
launch_ngpm
if [ "$DRY_RUN" = false ]; then
post_install_summary
else
log_success "=========================================================="
log_success "======= DRY RUN SELESAI ======="
log_success "=== Tidak ada perubahan yang diterapkan pada sistem. ==="
log_success "=========================================================="
fi
}
# Memulai eksekusi skrip dengan semua argumen yang diberikan
main "$@"
\ No newline at end of file
......@@ -46,7 +46,7 @@
SSH_CONFIG="/etc/ssh/sshd_config"
SSH_BAK_DIR="/etc/ssh/sshd_config.bak"
FIREWALLD_ZONE="public"
DEFAULT_SSH_PORT=22222 # Port SSH default yang akan kita gunakan
DEFAULT_SSH_PORT=22222 # Port SSH default yang akan proses ini gunakan
DRY_RUN=false
NEW_SSH_PORT=""
ALLOW_USERS_LIST=""
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment