Commit 27f0ddab by Bambang Adrian

feat(cloudflare): release osrm install script v4.4, and setup cloudflare and its tunnel

parent e0c1aae9
### **Cheatsheet `cloudflared` CLI**
#### **1. Instalasi & Autentikasi Awal**
Perintah ini digunakan untuk setup awal dan menjaga `cloudflared` tetap terbarui.
| Perintah | Deskripsi | Contoh |
| :--- | :--- | :--- |
| `cloudflared tunnel login` | Mengautentikasi `cloudflared` dengan akun Cloudflare. Ini adalah langkah pertama yang wajib dilakukan. | `cloudflared tunnel login` |
| `cloudflared update` | Memeriksa dan menginstal versi terbaru `cloudflared`. | `cloudflared update` |
| `cloudflared --version` | Menampilkan versi `cloudflared` yang sedang terinstal. | `cloudflared --version` |
---
#### **2. Manajemen Tunnel (CRUD)**
Perintah untuk membuat, melihat, dan menghapus tunnel. Tunnel adalah koneksi aman antara server dan jaringan Cloudflare.
| Perintah | Deskripsi | Contoh |
| :--- | :--- | :--- |
| `cloudflared tunnel create <NAMA>` | Membuat tunnel baru dengan nama yang spesifik dan menghasilkan file kredensial (`<UUID>.json`). | `cloudflared tunnel create ngpm-tunnel` |
| `cloudflared tunnel list` | Menampilkan semua tunnel yang ada di akun beserta UUID dan statusnya. | `cloudflared tunnel list` |
| `cloudflared tunnel delete <NAMA/UUID>` | Menghapus tunnel secara permanen. Aksi ini tidak dapat diurungkan. | `cloudflared tunnel delete ngpm-tunnel` |
| `cloudflared tunnel info <NAMA/UUID>` | Menampilkan detail spesifik tentang sebuah tunnel, termasuk ID, CNAME, dan koneksi yang aktif. | `cloudflared tunnel info ngpm-tunnel` |
| `cloudflared tunnel cleanup <NAMA/UUID>` | Menghapus koneksi yang "terjebak" atau tidak aktif untuk sebuah tunnel. | `cloudflared tunnel cleanup ngpm-tunnel` |
---
#### **3. Menjalankan Tunnel**
Perintah untuk mengaktifkan tunnel dan mulai melewatkan trafik.
| Perintah | Deskripsi | Contoh |
| :--- | :--- | :--- |
| `cloudflared tunnel run <NAMA/UUID>` | Menjalankan tunnel dari baris perintah. Proses ini akan berjalan di foreground. Berguna untuk testing. | `cloudflared tunnel run ngpm-tunnel` |
| `cloudflared tunnel --config <PATH> run` | Menjalankan tunnel menggunakan file konfigurasi `config.yml`. Ini adalah cara yang direkomendasikan untuk produksi. | `cloudflared tunnel --config ~/.cloudflared/config.yml run` |
---
#### **4. Konfigurasi Routing DNS**
Menghubungkan tunnel ke nama domain publik.
| Perintah | Deskripsi | Contoh |
| :--- | :--- | :--- |
| `cloudflared tunnel route dns <NAMA/UUID> <HOSTNAME>` | Membuat CNAME record di DNS Cloudflare agar `HOSTNAME` menunjuk ke tunnel. | `cloudflared tunnel route dns ngpm-tunnel route.diffsquare.web.id` |
| `cloudflared tunnel route list` | Menampilkan semua rute DNS atau IP yang terkonfigurasi untuk tunnel di akun. | `cloudflared tunnel route list` |
**Catatan Penting:** Jika domain tidak dikelola oleh Cloudflare, harus membuat CNAME record secara manual di provider DNS. Target CNAME-nya adalah **`<UUID>.cfargotunnel.com`**.
---
#### **5. Menjalankan sebagai Service (Systemd)**
Cara terbaik untuk menjalankan tunnel di lingkungan produksi agar selalu aktif.
| Perintah | Deskripsi | Contoh |
| :--- | :--- | :--- |
| `sudo cloudflared service install` | Menginstal `cloudflared` sebagai service `systemd` di level sistem. Akan mencari `config.yml` di `/etc/cloudflared/`. | `sudo cloudflared service install` |
| `sudo cloudflared service uninstall` | Menghapus service `systemd` `cloudflared`. | `sudo cloudflared service uninstall` |
| `systemctl --user enable cloudflared` | **(Rootless)** Mengaktifkan service untuk user saat ini, agar berjalan otomatis saat login. | `systemctl --user enable cloudflared-tunnel.service` |
| `systemctl --user start cloudflared` | **(Rootless)** Memulai service untuk user saat ini. | `systemctl --user start cloudflared-tunnel.service` |
---
#### **6. Tunnel Cepat (Ad-hoc)**
Sangat berguna untuk membagikan layanan web lokal secara cepat dan sementara.
| Perintah | Deskripsi | Contoh |
| :--- | :--- | :--- |
| `cloudflared tunnel --url <URL>` | Membuat tunnel sementara dengan hostname acak (`<random-words>.trycloudflare.com`) yang meneruskan trafik ke URL lokal. | `cloudflared tunnel --url http://localhost:8080` |
---
#### **7. Diagnostik & Troubleshooting**
Perintah untuk membantu saat terjadi masalah.
| Perintah | Deskripsi | Contoh |
| :--- | :--- | :--- |
| `cloudflared tunnel --loglevel debug run` | Menjalankan tunnel dengan output log yang sangat detail. Sangat berguna untuk melacak masalah koneksi atau konfigurasi. | `cloudflared tunnel --loglevel debug --config config.yml run` |
| `tail -f /var/log/cloudflared.log` | **(Jika sebagai service sistem)** Melihat log `cloudflared` secara real-time. | `tail -f /var/log/cloudflared.log` |
| `journalctl --user -u cloudflared` | **(Jika sebagai service rootless)** Melihat log dari service `systemd` user. | `journalctl --user -u cloudflared-tunnel.service -f` |
\ No newline at end of file
### **Panduan Final Terkompilasi: Publikasi OSRM via Cloudflare Tunnel dengan 2 Domain (Free Tier)**
Dokumen ini menjelaskan langkah-langkah lengkap untuk mempublikasikan layanan OSRM (Backend & Frontend) dan Nginx Proxy Manager (NGPM) yang berjalan di Docker ke internet publik menggunakan Cloudflare Tunnel pada paket **Free Tier**, dengan menggunakan dua domain yang berbeda.
#### **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`.
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)**.
**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.
#### **Arsitektur Final**
1. **Akses Frontend:**
* Pengguna membuka `https://osrm.geotency.com`
* ➜ (DNS `geotency.com` melakukan 301 Redirect)
* ➜ Browser dialihkan ke `https://osrm.diffsquare.web.id`
* ➜ Cloudflare Edge ➜ Tunnel ➜ Server di `localhost:9966`
2. **Akses Backend (dari Frontend):**
* Aplikasi Frontend (di `osrm.diffsquare.web.id`) memanggil `https://route.geotency.com`
* ➜ (DNS `geotency.com` melakukan 301 Redirect)
* ➜ Browser dialihkan ke `https://route.diffsquare.web.id`
* ➜ Cloudflare Edge ➜ Tunnel ➜ Server di `localhost:5000`
3. **Akses NGPM (Untuk Admin):**
* membuka `https://tunnel.diffsquare.web.id`
* ➜ Cloudflare Edge ➜ Tunnel ➜ Server di `localhost:81`
---
### **Langkah-langkah Implementasi**
#### **Prasyarat**
1. Akun Cloudflare (paket Free).
2. Domain `diffsquare.web.id` telah ditambahkan ke Cloudflare dan nameserver-nya sudah mengarah ke Cloudflare.
3. Layanan OSRM dan NGPM sudah berjalan di Docker.
---
#### **Langkah 1: Pengaturan Cloudflare Tunnel di Server**
1. **Instal `cloudflared`** (jika belum):
```bash
# Untuk Rocky Linux / RHEL
sudo dnf install -y 'dnf-command(config-manager)'
sudo dnf config-manager --add-repo https://pkg.cloudflare.com/cloudflared-ascii.repo
sudo dnf install -y cloudflared
```
2. **Login ke Cloudflare:**
```bash
cloudflared tunnel login
```
Ikuti tautan yang muncul, pilih domain `diffsquare.web.id` dan otorisasi.
3. **Buat Tunnel:**
```bash
cloudflared tunnel create lls-tunnel
```
Catat **UUID Tunnel** yang muncul. Output juga akan menunjukkan lokasi file kredensial JSON (`<UUID>.json`) di `/home/sysadmin/.cloudflared/`.
---
#### **Langkah 2: Konfigurasi Tunnel untuk Merutekan Layanan**
1. **Siapkan Direktori dan File Konfigurasi:**
```bash
sudo mkdir -p /etc/cloudflared
sudo nano /etc/cloudflared/config.yml
```
2. **Isi `config.yml` dengan Konfigurasi Final:**
Ganti `<YOUR_TUNNEL_UUID>` dengan UUID yang catat sebelumnya.
```yaml
# Lokasi: /etc/cloudflared/config.yml
tunnel: <YOUR_TUNNEL_UUID>
credentials-file: /etc/cloudflared/<YOUR_TUNNEL_UUID>.json
# Aturan routing lalu lintas
ingress:
# 1. Arahkan 'osrm.diffsquare.web.id' LANGSUNG ke Frontend OSRM
- hostname: osrm.diffsquare.web.id
service: http://localhost:9966
# 2. Arahkan 'route.diffsquare.web.id' LANGSUNG ke Backend OSRM Car
- hostname: route.diffsquare.web.id
service: http://localhost:5000
# 3. Arahkan 'tunnel.diffsquare.web.id' ke NGPM (untuk akses admin)
- hostname: tunnel.diffsquare.web.id
service: http://localhost:81
# Aturan terakhir untuk menangkap semua permintaan lain
- service: http_status:404
```
3. **Pindahkan File Kredensial dan Amankan Izin:**
```bash
# Ganti <YOUR_TUNNEL_UUID>.json dengan nama file
sudo mv /home/sysadmin/.cloudflared/<YOUR_TUNNEL_UUID>.json /etc/cloudflared/
# Atur kepemilikan dan izin yang benar
sudo chown root:root /etc/cloudflared/*
sudo chmod 644 /etc/cloudflared/config.yml
sudo chmod 600 /etc/cloudflared/<YOUR_TUNNEL_UUID>.json
```
---
#### **Langkah 3: Buat Rute DNS di Cloudflare dan Jalankan Tunnel**
1. **Perintahkan `cloudflared` untuk membuat Rute DNS:**
Perintah ini akan membuat record CNAME yang diperlukan di dasbor DNS `diffsquare.web.id`.
```bash
cloudflared tunnel route dns lls-tunnel osrm.diffsquare.web.id
cloudflared tunnel route dns lls-tunnel route.diffsquare.web.id
cloudflared tunnel route dns lls-tunnel tunnel.diffsquare.web.id
```
2. **Instal dan Jalankan Tunnel sebagai Layanan Sistem:**
```bash
sudo cloudflared service install
sudo systemctl enable --now cloudflared
```
3. **Verifikasi Layanan Tunnel:**
```bash
sudo systemctl status cloudflared
```
Pastikan outputnya menunjukkan `Active: active (running)`.
---
#### **Langkah 4: Konfigurasi Ulang OSRM Frontend**
1. **Edit file `docker-compose`:**
```bash
nano /home/sysadmin/data/docker-data/osrm/docker-compose.indonesia.yml
```
2. **Ubah Variabel Lingkungan `OSRM_BACKEND`:**
Pastikan nilainya adalah domain teknis (`diffsquare.web.id`) dan gunakan sintaks `map` (tanpa `-` dan tkutip) untuk menghindari error.
```yaml
# ... bagian dari docker-compose.indonesia.yml
osrm-frontend-indonesia:
# ... image, container_name, restart ...
environment:
OSRM_BACKEND: https://route.diffsquare.web.id
OSRM_MAPBOX_TOKEN: 'pk.eyJ1IjoiaXRsbHMiLCJhIjoiY21nc2QxdDBjMzcxNjJtcTJodzV0aHRzcSJ9.EcVZI7KfUuHDSSdMNRV3CA'
OSRM_CENTER: '-6.2,106.8'
OSRM_ZOOM: '13'
# ... sisa file
```
3. **Terapkan Perubahan:**
```bash
cd /home/sysadmin/data/docker-data/osrm
docker compose -f docker-compose.indonesia.yml up -d --force-recreate osrm-frontend-indonesia
```
---
#### **Langkah 5: Konfigurasi DNS di `geotency.com` (Metode Redirect)**
1. Login ke panel kontrol DNS provider untuk **`geotency.com`**.
2. **HAPUS SEMUA RECORD `CNAME`** yang sebelumnya buat untuk `osrm` dan `route`.
3. Cari fitur bernama **"Forwarding"**, **"Redirect"**, atau **"Pengalihan URL"**.
4. Buat **dua** aturan pengalihan:
* **Aturan 1 (Frontend):**
* **Sumber/Source:** `osrm.geotency.com`
* **Tujuan/Destination:** `https://osrm.diffsquare.web.id`
* **Tipe:** `Permanent (301)`
* **Aturan 2 (Backend):**
* **Sumber/Source:** `route.geotency.com`
* **Tujuan/Destination:** `https://route.diffsquare.web.id`
* **Tipe:** `Permanent (301)`
5. Simpan perubahan. Propagasi DNS untuk redirect mungkin memerlukan waktu beberapa saat.
---
### **Verifikasi Final**
1. **Akses Teknis:** Buka browser dan akses:
* `https://osrm.diffsquare.web.id` -> Harus menampilkan OSRM Frontend.
* `https://route.diffsquare.web.id` -> Harus menampilkan respons JSON dari OSRM Backend.
* `https://tunnel.diffsquare.web.id` -> Harus menampilkan halaman login NGPM.
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
tunnel: 13957c21-14cc-46e1-9a31-2b5b707a47d7
credentials-file: /etc/cloudflared/13957c21-14cc-46e1-9a31-2b5b707a47d7.json
ingress:
- hostname: tunnel.diffsquare.web.id
service: http://localhost:81
- hostname: osrm.diffsquare.web.id
service: http://localhost:9966
- hostname: route.diffsquare.web.id
service: http://localhost:81
- service: http_status:404
\ No newline at end of file
### **Peringatan Penting**
Tindakan ini bersifat **destruktif dan tidak dapat diurungkan**. Setelah tunnel dihapus, semua hostname yang terhubung dengannya akan berhenti berfungsi hingga membuat dan mengonfigurasi tunnel yang baru.
---
### **Langkah 1: Hentikan dan Nonaktifkan Service Tunnel yang Berjalan**
Sebelum menghapus tunnel, harus memastikan tidak ada proses `cloudflared` yang sedang aktif mencoba terhubung dengannya.
Karena menggunakan setup rootless, jalankan perintah berikut:
```bash
# Menghentikan service yang sedang berjalan
systemctl --user stop cloudflared-tunnel.service
# Mencegah service berjalan lagi saat boot/login berikutnya
systemctl --user disable cloudflared-tunnel.service
# Memverifikasi bahwa service sudah tidak aktif
systemctl --user status cloudflared-tunnel.service
```
seharusnya melihat output yang menunjukkan status `inactive (dead)`.
### **Langkah 2: Hapus Rute DNS yang Terhubung ke Tunnel**
Sangat penting untuk menghapus CNAME record yang mengarahkan domain ke tunnel.
**A. Untuk Domain yang Dikelola Cloudflare (`diffsquare.web.id`)**
Cara termudah dan paling visual adalah melalui Cloudflare Dashboard:
1. Login ke dashboard Cloudflare.
2. Pilih domain `diffsquare.web.id`.
3. Pergi ke menu **DNS** -> **Records**.
4. Cari CNAME record yang مرتبط dengan tunnel. Biasanya, **Name**-nya adalah `route` dan **Content**-nya adalah `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.cfargotunnel.com`.
5. Klik **Edit**, lalu **Delete** dan konfirmasi penghapusan.
**B. Untuk Domain yang Dikelola Pihak Ketiga (`geotency.com`)**
1. Login ke panel DNS provider tempat mengelola `geotency.com`.
2. Cari CNAME record untuk `route.geotency.com`.
3. Hapus record tersebut.
### **Langkah 3: Hapus Tunnel dari Cloudflare**
Ini adalah langkah inti di mana menghapus tunnel itu sendiri dari infrastruktur Cloudflare.
1. **Cari Nama atau UUID Tunnel:**
Jalankan perintah `list` untuk melihat semua tunnel yang terdaftar di akun.
```bash
cloudflared tunnel list
```
Outputnya akan terlihat seperti ini, catat **NAME** atau **ID** dari tunnel yang ingin hapus (misalnya, `lls-tunnel`).
```
ID NAME CREATED CONNECTIONS
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx lls-tunnel 2025-10-21T12:00:00Z 2 connected
```
2. **Jalankan Perintah Hapus:**
Gunakan nama atau UUID yang catat untuk menjalankan perintah `delete`.
```bash
# Menggunakan NAMA tunnel
cloudflared tunnel delete lls-tunnel
# Atau menggunakan UUID tunnel
cloudflared tunnel delete xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
```
3. **Konfirmasi Penghapusan:**
`cloudflared` akan meminta konfirmasi terakhir. Ketik `y` dan tekan Enter.
```
Are you sure you want to delete tunnel lls-tunnel [y/N]? y
Successfully deleted tunnel lls-tunnel
```
### **Langkah 4: Hapus File Konfigurasi dan Kredensial Lokal**
Untuk benar-benar "memulai dari awal", hapus file konfigurasi dan file kredensial JSON dari server.
1. **Hapus File Konfigurasi:**
```bash
rm ~/.cloudflared/config.yml
```
2. **Hapus File Kredensial Tunnel:**
File ini dinamai sesuai dengan UUID tunnel.
```bash
# Ganti <UUID>.json dengan nama file yang sebenarnya
rm ~/.cloudflared/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.json
```
3. **(Opsional) Hapus File Service `systemd`:**
Jika ingin menghapus definisi service juga.
```bash
rm ~/.config/systemd/user/cloudflared-tunnel.service
systemctl --user daemon-reload
```
### **Langkah Verifikasi**
Untuk memastikan semuanya sudah bersih:
1. Jalankan `cloudflared tunnel list` sekali lagi. Tunnel yang hapus seharusnya sudah tidak ada di daftar.
2. Periksa **Cloudflare Zero Trust Dashboard**. Pergi ke **Access** -> **Tunnels**. Tunnel tersebut seharusnya sudah hilang dari daftar.
---
**Selesai!** Sekarang berada dalam kondisi bersih dan siap untuk membuat tunnel baru dari awal dengan mengikuti perintah `cloudflared tunnel create <NAMA_BARU>`.
# KONFLIK DENGAN SERVICE CLOUDFLARED SEBELUMNYA
## USER VS SYSTEM
### **Analisis Situasi**
Mari kita 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`.
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`.
* **Konflik Port atau Koneksi**: Kedua proses mungkin mencoba mengelola tunnel yang sama atau berbeda, menyebabkan perilaku yang tidak terduga.
* **Masalah Izin**: Proses yang berjalan sebagai `root` mungkin memiliki izin yang berbeda untuk mengakses jaringan Docker dibandingkan proses yang berjalan sebagai user `sysadmin`.
### **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`.
### **Langkah-Langkah untuk Menonaktifkan Service Sistem**
Silakan jalankan perintah berikut secara berurutan. Perhatikan penggunaan `sudo` karena kita berinteraksi dengan service sistem.
1. **Hentikan Service Sistem:**
Perintah ini akan menghentikan proses `cloudflared` (PID 1571) yang sedang berjalan.
```bash
sudo systemctl stop cloudflared
```
2. **Nonaktifkan Service Sistem:**
Perintah ini akan mencegah service `cloudflared` level sistem untuk berjalan lagi secara otomatis saat server di-reboot.
```bash
sudo systemctl disable cloudflared
```
3. **Verifikasi Status:**
Sekarang, periksa kembali statusnya.
```bash
sudo systemctl status cloudflared
```
Output yang diharapkan seharusnya menunjukkan bahwa service tersebut `inactive (dead)` dan `disabled`.
```
○ cloudflared.service - cloudflared
Loaded: loaded (/etc/systemd/system/cloudflared.service; disabled; preset: disabled)
Active: inactive (dead) since ...
```
### **(Opsional tapi Direkomendasikan) Membersihkan File Konfigurasi Sistem**
Setelah service dinonaktifkan, file konfigurasi di `/etc/cloudflared/` tidak lagi digunakan. Untuk kebersihan, sebaiknya memindahkannya sebagai backup atau menghapusnya. Memindahkannya lebih aman.
```bash
# Pindahkan direktori konfigurasi lama menjadi backup
sudo mv /etc/cloudflared /etc/cloudflared.backup
# (Jika benar-benar yakin) Hapus direktori tersebut
# sudo rm -rf /etc/cloudflared
```
### **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
#!/bin/bash
# Assign a random value to the password variable
rustdesk_pw=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 8 | head -n 1)
# Get your config string from your Web portal and Fill Below
rustdesk_cfg="configstring"
################################## Please Do Not Edit Below This Line #########################################
# Check if the script is being run as root
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root."
exit 1
fi
# Identify OS
if [ -f /etc/os-release ]; then
# freedesktop.org and systemd
. /etc/os-release
OS=$NAME
VER=$VERSION_ID
UPSTREAM_ID=${ID_LIKE,,}
# Fallback to ID_LIKE if ID was not 'ubuntu' or 'debian'
if [ "${UPSTREAM_ID}" != "debian" ] && [ "${UPSTREAM_ID}" != "ubuntu" ]; then
UPSTREAM_ID="$(echo ${ID_LIKE,,} | sed s/\"//g | cut -d' ' -f1)"
fi
elif type lsb_release >/dev/null 2>&1; then
# linuxbase.org
OS=$(lsb_release -si)
VER=$(lsb_release -sr)
elif [ -f /etc/lsb-release ]; then
# For some versions of Debian/Ubuntu without lsb_release command
. /etc/lsb-release
OS=$DISTRIB_ID
VER=$DISTRIB_RELEASE
elif [ -f /etc/debian_version ]; then
# Older Debian, Ubuntu, etc.
OS=Debian
VER=$(cat /etc/debian_version)
elif [ -f /etc/SuSE-release ]; then
# Older SuSE etc.
OS=SuSE
VER=$(cat /etc/SuSE-release)
elif [ -f /etc/redhat-release ]; then
# Older Red Hat, CentOS, etc.
OS=RedHat
VER=$(cat /etc/redhat-release)
else
# Fall back to uname, e.g. "Linux <version>", also works for BSD, etc.
OS=$(uname -s)
VER=$(uname -r)
fi
# Install RustDesk
echo "Installing RustDesk"
if [ "${ID}" = "debian" ] || [ "$OS" = "Ubuntu" ] || [ "$OS" = "Debian" ] || [ "${UPSTREAM_ID}" = "ubuntu" ] || [ "${UPSTREAM_ID}" = "debian" ]; then
wget https://github.com/rustdesk/rustdesk/releases/download/1.2.6/rustdesk-1.2.6-x86_64.deb
apt-get install -fy ./rustdesk-1.2.6-x86_64.deb > null
elif [ "$OS" = "CentOS" ] || [ "$OS" = "RedHat" ] || [ "$OS" = "Fedora Linux" ] || [ "${UPSTREAM_ID}" = "rhel" ] || [ "$OS" = "Almalinux" ] || [ "$OS" = "Rocky*" ] ; then
wget https://github.com/rustdesk/rustdesk/releases/download/1.2.6/rustdesk-1.2.6-0.x86_64.rpm
yum localinstall ./rustdesk-1.2.6-0.x86_64.rpm -y > null
else
echo "Unsupported OS"
# here you could ask the user for permission to try and install anyway
# if they say yes, then do the install
# if they say no, exit the script
exit 1
fi
# Run the rustdesk command with --get-id and store the output in the rustdesk_id variable
rustdesk_id=$(rustdesk --get-id)
# Apply new password to RustDesk
rustdesk --password $rustdesk_pw &> /dev/null
rustdesk --config $rustdesk_cfg
systemctl restart rustdesk
echo "..............................................."
# Check if the rustdesk_id is not empty
if [ -n "$rustdesk_id" ]; then
echo "RustDesk ID: $rustdesk_id"
else
echo "Failed to get RustDesk ID."
fi
# Echo the value of the password variable
echo "Password: $rustdesk_pw"
echo "..............................................."
\ No newline at end of file
......@@ -2,12 +2,11 @@
#
# install-osrm-ngpm.sh
# OSRM + NGPM installer & manager (Rocky Linux 10)
# Final self-contained script (v4.3 - Final Execution Logic Fix)
# Final self-contained script (v4.4 - Frontend URL Format Fix)
#
set -euo pipefail
IFS=$'\n\t'
# ... (Seluruh bagian DEFAULTS hingga Core Action Functions sama persis seperti v4.2) ...
# -------------------------
# DEFAULTS
# -------------------------
......@@ -63,7 +62,7 @@ err() { _log "ERROR" "$*" >&2; }
# -------------------------
usage() {
cat <<EOF
OSRM Installer & Manager v4.3
OSRM Installer & Manager v4.4
Usage:
$0 <command> --map-name <name> [options]
Commands:
......@@ -128,7 +127,6 @@ ask_confirm() { local prompt="$1"; if [ "${yes_all}" = true ]; then info "[auto-
# Core Action Functions
# -------------------------
action_prepare_map() {
# ... (same as v4.2)
info "Preparing map from source: ${map_source}"
local map_instance_dir="${work_dir}/${map_name}/dataset"
mkdir -p "${map_instance_dir}"
......@@ -142,7 +140,6 @@ action_prepare_map() {
fi
}
action_create_profile_file() {
# ... (same as v4.2)
local profile="$1"
local profiles_dir="${work_dir}/${map_name}/profiles"
mkdir -p "${profiles_dir}"
......@@ -169,10 +166,10 @@ LUA
esac
}
action_run_preprocessing() {
# ... (same as v4.2)
local profile="$1"
local map_instance_dir="${work_dir}/${map_name}"
local pdata_dir="${map_instance_dir}/${profile}-data"
mkdir -p "${pdata_dir}"
info "Preparing map for profile '${profile}'..."; cp -vf "${MAP_PATH}" "${pdata_dir}/map.osm.pbf"
local service_name="osrm-preprocess-${map_name}-${profile}"
info "--- Processing profile: ${profile} ---"
......@@ -186,23 +183,20 @@ action_run_preprocessing() {
docker compose -f "${COMPOSE_FILE}" rm -fsv "${service_name}" >/dev/null 2>&1 || true
}
action_update_compose_file() {
# ... (same as v4.2)
info "Writing new configuration to ${COMPOSE_FILE}..."
echo "$1" > "$2"
success "File ${COMPOSE_FILE} updated."
}
action_recreate_container() {
# ... (same as v4.2)
local service_name="$1"
info "Applying changes to container '${service_name}'..."
if ! docker compose -f "${COMPOSE_FILE}" up -d --remove-orphans "${service_name}"; then
if ! docker compose -f "${COMPOSE_FILE}" up -d --remove-orphans --force-recreate "${service_name}"; then
err "Failed to create/recreate container '${service_name}'."
return 1
fi
success "Container '${service_name}' is up to date."
}
generate_docker_compose_content() {
# ... (same as v4.2 - already correct)
local map_instance_dir="${work_dir}/${map_name}"; local selabel="${SELINUX_LABEL:-}"; local patched_dir="${map_instance_dir}/patched-profiles"
local compose_content="services:\n"
local idx=0
......@@ -236,12 +230,12 @@ generate_docker_compose_content() {
done
if [ "${no_frontend}" != true ]; then
if [ -z "${mapbox_token}" ]; then warn "Mapbox token not provided."; fi
local backend_urls=""; local first=true
for profile in "${PROFILE_ARR[@]}"; do
local label; label="$(tr '[:lower:]' '[:upper:]' <<< ${profile:0:1})${profile:1}"
local backend_service_name="osrm-routed-${map_name}-${profile}"
if [[ "$first" == "true" ]]; then backend_urls+="${label}|http://${backend_service_name}:5000/route/v1"; first=false; else backend_urls+=",${label}|http://${backend_service_name}:5000/route/v1"; fi
done
# --- FIX IS HERE (v4.4) ---
# Set the backend URL to a single, browser-accessible endpoint.
# This uses the port of the *first* profile specified.
local backend_url="http://localhost:${backend_port}"
local depends_on_yaml=""; for profile in "${PROFILE_ARR[@]}"; do depends_on_yaml+=$(printf '\n - osrm-routed-%s-%s' "${map_name}" "${profile}"); done
frontend_yaml=$(printf '
osrm-frontend-%s:
......@@ -258,7 +252,7 @@ generate_docker_compose_content() {
networks:
- %s
depends_on:%s
' "${map_name}" "${DEFAULT_FRONTEND_REGISTRY}" "${DEFAULT_FRONTEND_VERSION}" "${map_name}" "${backend_urls}" "${mapbox_token}" "${map_center}" "${map_zoom}" "${frontend_port}" "${network_name}" "${depends_on_yaml}")
' "${map_name}" "${DEFAULT_FRONTEND_REGISTRY}" "${DEFAULT_FRONTEND_VERSION}" "${map_name}" "${backend_url}" "${mapbox_token}" "${map_center}" "${map_zoom}" "${frontend_port}" "${network_name}" "${depends_on_yaml}")
compose_content+="${frontend_yaml}"
fi
compose_content+=$(printf '\nnetworks:\n %s:\n external: true\n name: %s\n' "${network_name}" "${network_name}")
......@@ -290,10 +284,16 @@ main() {
fi
local plan_profiles_to_create=(); for profile in "${PROFILE_ARR[@]}"; do if [ ! -f "${profiles_dir}/${profile}.lua" ]; then plan_profiles_to_create+=("${profile}"); fi; done
local plan_profiles_to_preprocess=()
if [[ "${map_changed}" == "true" || ("${command_name}" == "update" && "${sub_command}" == "profile") ]]; then
if [[ "${map_changed}" == "true" || ("${command_name}" == "update" && "${sub_command}" == "profile") || "${command_name}" == "install" ]]; then
for profile in "${PROFILE_ARR[@]}"; do
# For install, always schedule preprocessing if data doesn't exist
if [ ! -f "${map_instance_dir}/${profile}-data/${map_name}-${profile}.osrm.properties" ]; then
plan_profiles_to_preprocess+=("${profile}")
fi
done
if [[ "${command_name}" != "install" ]]; then
plan_profiles_to_preprocess=("${PROFILE_ARR[@]}")
else
for profile in "${PROFILE_ARR[@]}"; do if [ ! -f "${map_instance_dir}/${profile}-data/${map_name}-${profile}.osrm.properties" ]; then plan_profiles_to_preprocess+=("${profile}"); fi; done
fi
fi
local plan_compose_update=false
local new_compose_content; new_compose_content=$(generate_docker_compose_content)
......@@ -326,8 +326,6 @@ main() {
for profile in "${plan_profiles_to_preprocess[@]}"; do if [[ "${decisions[preprocess_${profile}]:-false}" == "true" ]]; then action_run_preprocessing "${profile}" || warn "Preprocessing untuk ${profile} gagal."; else info "Preprocessing untuk '${profile}' dilewati."; fi; done
# --- FIX IS HERE (v4.3) ---
# This block now correctly executes the container actions based on decisions.
info "Menjalankan: Sinkronisasi Container..."
local services_to_run=()
for service in "${all_services[@]}"; do
......@@ -360,7 +358,6 @@ main() {
success "Proses selesai!"; print_summary
}
# ... (sisa fungsi tidak berubah)
run_remove() { info "Starting removal of OSRM instance: '${map_name}'"; if [ ! -f "${COMPOSE_FILE}" ]; then warn "Instance '${map_name}' not found."; fi; if ask_confirm "This will STOP and REMOVE all containers for instance '${map_name}'. Are you sure?"; then if [ -f "${COMPOSE_FILE}" ]; then docker compose -f "${COMPOSE_FILE}" down -v || warn "Could not stop containers."; fi; if [[ "${do_purge}" == "true" ]]; then local instance_dir="${work_dir}/${map_name}"; if ask_confirm "PURGE ENABLED. This will DELETE '${instance_dir}'. IRREVERSIBLE. Proceed?"; then rm -rf "${instance_dir}"; rm -f "${COMPOSE_FILE}"; success "Instance data for '${map_name}' has been purged."; fi; fi; else info "Removal aborted by user."; fi; }
print_summary() { echo "--- Instance '${map_name}' Summary ---"; echo "Profiles: ${profiles_csv}"; echo "ACCESS POINTS:"; local idx=0; for profile in "${PROFILE_ARR[@]}"; do idx=$((idx + 1)); local host_port=$((backend_port + idx - 1)); echo " - Backend (${profile}): http://localhost:${host_port}"; echo " (NGPM Target: osrm-routed-${map_name}-${profile}:5000)"; done; if [ "${no_frontend}" != true ]; then echo " - Frontend UI: http://localhost:${frontend_port}"; echo " (NGPM Target: osrm-frontend-${map_name}:9966)"; fi; echo "--------------------------"; }
......
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