DocsMulai
Mulai dari VPS baru
Semua langkah dari VPS baru sampai panel aoox bisa dibuka di domain sendiri, siap disalin dan berurutan.
- Waktu
- ± 30 menit (DNS bisa lebih lama)
- Butuh
- VPS Linux baru (amd64 atau arm64) dan, untuk HTTPS, sebuah domain
- Hasil
- Panel di https://panel.example.com
Placeholder yang dipakai di bawah: SERVER_IP adalah IP publik VPS-mu, your-user adalah login yang kamu buat di langkah 4, dan panel.example.com / api.panel.example.com adalah nama domainmu sendiri. Sudah punya server dengan Docker dan hanya butuh instalasinya? Lihat Instalasi.
1. Memilih VPS
| Minimum | Disarankan | |
|---|---|---|
| CPU | 1 vCPU | 2 vCPU atau lebih |
| RAM | 2 GB (tambah swap, langkah 5) | 4 GB atau lebih |
| Disk | 25 GB SSD | 40 GB SSD atau lebih |
RAM 2 GB dengan swap adalah minimum yang sudah diuji. Di VPS Ubuntu 1 vCPU / 2 GB dengan swap, panel, proxy, registry, build Dockerfile, static dan Nixpacks, database, backup, server remote, dan Swarm satu node semuanya berjalan; build Nixpacks pertama (dingin) memakan sekitar 5 menit (build berikutnya 12 detik), sedangkan build Railpack pertama bisa dimatikan karena kehabisan memori (kode keluar 137). Pakai 4 GB atau lebih untuk Railpack atau beberapa database. Panel sendiri tiga container (PostgreSQL, API, dan aplikasi web); reverse proxy dan registry lokal ditambahkan saat kamu mengaktifkannya; dan setiap build berjalan di mesin yang sama. Di VPS 1 vCPU / 2 GB, stack panel yang menganggur sudah memakai sekitar 600-900 MB sebelum ada aplikasi, dan satu build (misalnya next build, Nixpacks, atau Railpack) butuh 1-2 GB lagi dan bisa memakai swap walaupun begitu. Yang banyak memakai memori dan disk adalah build dan aplikasimu: image helper Nixpacks saja sekitar 350 MB, image lama menumpuk, dan build yang kehabisan memori langsung gagal. RAM 1 GB hanya cukup untuk server remote (tanpa panel, hanya Docker, proxy, dan aplikasimu), dengan swap.
- Arsitektur: x86_64 (amd64) atau arm64. Image
hideandseeklab/aoox-apidanhideandseeklab/aoox-webdipublikasikan untuk keduanya mulai 0.1.0-alpha.13. Image 0.1.0-alpha.12 dan sebelumnya hanya amd64, jadi VPS ARM (Ampere, Graviton) membutuhkan 0.1.0-alpha.13 atau lebih baru; CLI aoox sendiri sudah punya build arm64. - Sistem operasi: Linux umum dengan systemd, misalnya Ubuntu 24.04 / 22.04 LTS atau Debian 12. Installer hanya memeriksa bahwa ia berjalan di Linux; syarat sebenarnya adalah distribusimu didukung skrip instalasi Docker (
get.docker.com). Perintah di bawah ditulis untuk Ubuntu dan Debian. Alpine (musl) tidak didukung oleh CLI siap-pakai. - Firewall / security group dari provider. Kalau providermu punya, buka masuk
22(SSH),80dan443(HTTPS dan sertifikat), plus3000dan3001sampai domain berfungsi (80/443 baru menjawab setelah domain panel pertama disimpan, langkah 10). Jangan buka5000(registry lokal, langkah 11) kecuali kamu memakai node Swarm.
2. Login SSH pertama
Provider menampilkan IP, user pertama (root di kebanyakan,ubuntu di sebagian image cloud), dan password atau key yang kamu pilih saat membuat server.
ssh root@SERVER_IPubuntu. Kalau begitu sambungkan dengan ssh ubuntu@SERVER_IP dan tambahkan sudo di depan perintah di bawah yang ditulis tanpa itu (langkah 3 dan 4). Kamu boleh melewati pembuatan user baru di langkah 4 dan memakai ubuntu sebagai your-user.Windows 10/11 sudah menyertakan klien OpenSSH, jadi perintah yang sama jalan di PowerShell. Pertama kali, SSH menampilkan fingerprint server dan bertanya Are you sure you want to continue connecting. Kalau providermu menampilkan fingerprint di konsolnya, cocokkan dulu; lalu ketik yes. Kalau server dibangun ulang dan SSH mengeluh host identification berubah, hapus entri lama dengan ssh-keygen -R SERVER_IP.
3. Perbarui sistem
sudo apt update && sudo apt upgrade -yDi Ubuntu, sebuah file muncul saat reboot diperlukan (misalnya setelah update kernel). Di Debian, reboot setelah upgrade kernel.
[ -f /var/run/reboot-required ] && sudo rebootSambung lagi dengan perintah ssh yang sama setelah sekitar semenit.
4. User sudo dan login dengan SSH key
Jangan bekerja sehari-hari sebagai root. Langkah ini juga penting untuk aoox: kalau kamu menginstal sebagai user sudo, aoox memakai user itu untuk web terminal. Instalasi baru menulis TERMINAL_SSH_USER dengan user yang menjalankan sudo dan mengotorisasi key terminal untuknya; kalau kamu menginstal langsung sebagai root, user terminal adalah root, yang ditolak lewat SSH oleh kebanyakan image cloud. (Kalau image-mu sudah memberi user sudo seperti ubuntu, kamu boleh melewati pembuatan user dan memakainya.)
Buat user (di server)
adduser your-userusermod -aG sudo your-useraddusermeminta password dan beberapa detail opsional. Simpan passwordnya:sudomemintanya.Buat key di laptop (lewati kalau sudah punya)
ssh-keygen -t ed25519 -C "kamu@laptop"Hasilnya
~/.ssh/id_ed25519(privat, jangan dibagikan) dan~/.ssh/id_ed25519.pub(publik). Passphrase sebaiknya dipakai.Pasang public key di server
macOS / Linux, dari laptop:
ssh-copy-id your-user@SERVER_IPPowerShell Windows tidak punya
ssh-copy-id; ini hasilnya sama (akan meminta password yang baru kamu buat):Get-Content $env:USERPROFILE\.ssh\id_ed25519.pub | ssh your-user@SERVER_IP "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"Tes di terminal kedua
Biarkan sesi root tetap terbuka dan, di jendela terminal baru:
ssh your-user@SERVER_IPsudo -vKamu harus bisa masuk dengan key (tanpa password server; permintaan passphrase key tidak masalah), dan
sudo -vmenerima passwordmu. Lanjut hanya kalau keduanya berhasil.
Opsional: matikan login password dan root
Ubuntu dan Debian membaca file tambahan dari /etc/ssh/sshd_config.d/ lebih dulu, dan untuk tiap setelan nilai pertama yang ditemukan yang dipakai, jadi file bawaan image cloud (sering 50-cloud-init.conf dengan PasswordAuthentication yes) akan mengalahkan perubahan di sshd_config utama. File bernama 10-… dibaca sebelumnya:
sudo tee /etc/ssh/sshd_config.d/10-hardening.conf <<'EOF'
PasswordAuthentication no
PermitRootLogin no
EOFsudo sshd -t && sudo systemctl reload sshsshd -t tidak mencetak apa-apa kalau konfigurasinya valid. Lalu buka terminal ketiga dan pastikan ssh your-user@SERVER_IP masih berfungsi. Dua catatan terkait aoox: web terminal masuk lewat SSH dengan key, jadi tetap jalan dengan PasswordAuthentication no; tetapi ia gagal kalau TERMINAL_SSH_USER adalah root dan login root dimatikan, dan kalau kamu membatasi SSH dengan AllowUsers user terminal harus tercantum. Lihat User SSH di VPS cloud.
Mulai sekarang, login sebagai your-user.
5. Dasar: zona waktu, swap, firewall
Zona waktu
timedatectl list-timezones | grep -i jakartasudo timedatectl set-timezone Asia/JakartaPilih zonamu dari daftar itu. Ini hanya mengatur jam host untuk log dan cron di host. Jadwal aoox sendiri (job, backup, pembersihan malam) berjalan di dalam container API yang memakai UTC kecuali kamu mengisi TZ. Supaya berjalan di zonamu, tambahkan ke .env.dist lalu buat ulang container API. Lakukan ini setelah langkah 8 (instalasi): /opt/aoox belum ada sebelumnya, jadi perintah di bawah gagal kalau dijalankan sekarang.
echo 'TZ=Asia/Jakarta' | sudo tee -a /opt/aoox/.env.dist
cd /opt/aoox && sudo docker compose -f docker-compose.dist.yml --env-file .env.dist up -dDashboard menampilkan zona yang dipakai di samping setiap field jadwal. Instalasi yang dibuat sebelum opsi ini ada perlu aoox reinstall dulu agar compose-nya meneruskan TZ ke API. Ekspresi cron yang sudah ada tetap angkanya, jadi periksa lagi setelah mengganti zona.
Swap (disarankan di bawah 4 GB RAM)
Swap file membuat build bertahan saat memori melonjak sebentar, bukannya dimatikan.
Cek dulu: banyak image sudah membawa swap. Kalau salah satu perintah di bawah menampilkan baris swap berukuran, lewati bagian ini (menambah swap file kedua hanya membuang disk).
swapon --show
free -hsudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfileecho '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstabfree -hfree -h harus menampilkan 2.0Gi di baris Swap. Sebagian provider sudah menambah swap atau memakai filesystem yang tidak bisa menjadikan file hasil fallocate sebagai swap; kalau swapon mengeluh, cek swapon --show dulu.
Firewall (ufw)
sudo apt install -y ufwsudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 3000/tcp
sudo ufw allow 3001/tcp
sudo ufw --force enable
sudo ufw status verbose--force penting kalau seluruh blok ditempel sekaligus: ufw enable biasa berhenti dan bertanya Command may disrupt existing ssh connections. Proceed with operation (y|n)?, lalu baris yang tersisa terbaca sebagai jawabannya, sehingga ufw tetap mati. Aturan SSH sudah ditambahkan lebih dulu, jadi mengaktifkannya tidak memutus sesimu.
Port 3000/3001 hanya dibutuhkan sampai domain berfungsi (langkah 10). Biarkan aturan 22 terbuka untuk semua sumber: web terminal tersambung dari container API ke port SSH host, jadi aturan yang dibatasi ke IP-mu sendiri akan memblokirnya.
ufw deny 3000, dan hal yang sama berlaku untuk registry di port 5000 setelah kamu mengaktifkannya (dilindungi password, tetapi tetap terbuka) dan untuk host port yang kamu beri pada aplikasi. Untuk benar-benar menutupnya pakai firewall provider (ia menyaring sebelum lalu lintas sampai ke VM), dan untuk panel pakai saklar Hanya izinkan akses lewat domain, yang membuat port 3000/3001 hanya mendengarkan di 127.0.0.1. ufw tetap berguna untuk semua yang tidak dipublikasikan Docker (SSH dan layanan host lain). Ini sudah diuji di VPS Ubuntu 24.04 sungguhan: port yang ditolak ufw tetap bisa dijangkau dari luar. aoox membantu di dua tempat: database atau aplikasi admin database yang kamu publikasikan diikat ke 127.0.0.1 secara default, dan setiap host port lain (aplikasi, stack) punya pilihan Mendengarkan di, Publik atau Hanya server ini (127.0.0.1). Tab Port terbuka di halaman Docker (owner dan admin) menampilkan semua port yang dipublikasikan beserta pemiliknya dan apakah terbuka ke internet.6. Pasang CLI aoox (tanpa Node.js)
aoox install adalah perintah CLI aoox. Tarball CLI mandiri membawa Node.js sendiri, jadi kamu tidak perlu memasang Node.js di server. Jalankan dengan sudo agar terpasang di /usr/local/bin:
curl -fsSL https://aoox.dev/install-cli.sh | sudo shaoox --version~/.local/bin, lalu sudo aoox install di langkah berikutnya menjawab command not found (sudo tidak mencari di folder itu). Didukung: Linux dengan glibc (x64 atau arm64) dan macOS.Alternatif: npm (butuh Node.js 22 atau lebih baru)
CLI mensyaratkan node >= 22. Di Ubuntu/Debian, Node 22 dari NodeSource:
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -sudo apt-get install -y nodejssudo npm install -g @hideandseeklab/aoox7. Docker
Kamu tidak harus memasangnya sendiri. aoox install memeriksa apakah docker info berfungsi; kalau Docker belum ada atau tidak jalan, ia menawarkan menjalankan skrip resmi Docker (curl -fsSL https://get.docker.com | sh) dan meminta konfirmasi (--yes melewati pertanyaan). Sesudahnya ia memeriksa Docker berfungsi dan berhenti dengan petunjuk (systemctl status docker) kalau tidak.
Kalau kamu lebih suka memasang Docker sendiri dari repositori apt-nya dulu (Ubuntu; instalasi butuh plugin Compose v2):
sudo apt update
sudo apt install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.ascsudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "$VERSION_CODENAME")
Components: stable
Signed-By: /etc/apt/keyrings/docker.asc
EOFsudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-pluginDi Debian, ganti ubuntu dengan debian di URL key dan di baris URIs:. Cek dengan sudo docker compose version.
aoox install berjalan sebagai root dan tidak membutuhkan usermu ada di grup docker. Menambahkannya (sudo usermod -aG docker your-user, lalu login ulang) hanya menghemat mengetik sudo sebelum docker, dan itu setara akses root ke server: siapa pun yang bisa menjalankan docker bisa me-mount seluruh filesystem. Lewati kecuali kamu mau kenyamanan itu.8. Pasang aoox
Jalankan sebagai your-user (bukan login root), supaya user sudo menjadi user terminal:
sudo aoox installIa bertanya paling banyak dua hal, dan tidak ada dengan --yes:
Install Docker now via curl -fsSL https://get.docker.com | sh?hanya kalau Docker belum ada.Install aoox in /opt/aoox and run docker compose up -d? (Y/n)
Lalu ia melakukan, berurutan:
- Membuat
/opt/aoox(ubah dengan--dir) berisidocker-compose.dist.ymldan foldersecrets/milik uid 1000 (user container API). - Mendeteksi IP publik lewat
api.ipify.orgdan menulis/opt/aoox/.env.dist(mode 0600) denganPOSTGRES_PASSWORD,JWT_SECRET, danENCRYPTION_KEYyang baru dibuat acak,INSTALL_DIR=/opt/aoox(supaya dashboard nanti bisa mengganti domain panel tanpa setup tambahan), danTERMINAL_SSH_USER=your-user. - Membuat SSH key terminal di
secrets/dan menambahkannya ke~/.ssh/authorized_keysmilikyour-user. Masalah di sini hanya peringatan (--no-terminal-authorizemelewatinya). - Menjalankan
docker compose up -d, yang menarik PostgreSQL 16 dan dua image aoox, lalu menunggu API sampai dua menit (ia menjalankan migrasi database di start pertama).
Perkirakan beberapa menit, kebanyakan untuk mengunduh image. Selesainya:
aoox is installed in /opt/aoox.
Open: http://SERVER_IP:3000
Create the first owner account at /setup.3000 dan 3001 yang menjawab.http://localhost:3000, dan WEB_ORIGIN di .env.dist juga localhost. Ganti dengan IP aslimu di WEB_ORIGIN dan PUBLIC_API_URL, lalu jalankan sudo docker compose -f docker-compose.dist.yml --env-file .env.dist up -d di /opt/aoox: sign-in dan terminal memeriksa bahwa alamat di browser sama persis dengan WEB_ORIGIN.Log dan status sesudahnya (file-nya milik root, jadi pakai sudo):
cd /opt/aoox
sudo docker compose -f docker-compose.dist.yml --env-file .env.dist ps
sudo docker compose -f docker-compose.dist.yml --env-file .env.dist logs -f apisudo aoox install menolak jalan lagi di folder yang sudah berisi instalasi. --force memasang ulang di atasnya: lebih dulu menyalin .env.dist dan file compose ke /opt/aoox/backups/<timestamp>/ lalu mempertahankan secret yang ada, sehingga data tetap terbaca. Hanya --force --new-secrets --wipe-data yang mulai dari nol, dan itu menghapus database panel. Untuk memperbaiki atau menyegarkan instalasi pakai sudo aoox reinstall (langkah 11)./opt/aoox sudah dihapus tetapi Docker masih punya volume lama aoox_postgres_data, installer berhenti sebelum menulis apa pun: password database acak yang baru tidak bisa membuka data lama itu. Kembalikan .env.dist yang lama (misalnya dari /opt/aoox/backups/<timestamp>/) lalu jalankan sudo aoox reinstall untuk mempertahankan data, atau jalankan sudo aoox install --force --new-secrets --wipe-data untuk menghapus data itu dan mulai bersih.curl -fsSL https://aoox.dev/install.sh | sudo sh melakukan hal yang sama dengan environment variable sebagai ganti pertanyaan dan flag, dan hanya butuh curl dan sh. Lihat Instalasi. CLI tetap bisa dipasang sesudahnya untuk aoox update dan aoox domain.9. Sign-in pertama
Buka dashboard
Buka
http://SERVER_IP:3000. Selama belum ada user, kamu dialihkan ke/setup.Buat owner
Isi nama, email, dan password (minimal 8 karakter). Akun pertama ini adalah owner; user berikutnya diundang dari Settings (Pengguna & peran).
Cek dari server (opsional)
curl -s http://localhost:3001/auth/setup-status{"needsSetup":true}sebelum akun dibuat,{"needsSetup":false}sesudahnya.
10. Domain dengan HTTPS
Buat dua record DNS A
Di penyedia DNS-mu, arahkan dua nama ke IP server:
DNSpanel.example.com. A SERVER_IP api.panel.example.com. A SERVER_IPDashboard dan API butuh nama terpisah karena browser berbicara langsung ke API. Kalau memakai Cloudflare, set kedua record ke DNS only (awan abu-abu) selagi sertifikat diterbitkan.
Tunggu sampai ter-resolve
Dari laptop:
nslookup panel.example.comHarus menjawab
SERVER_IP. Sertifikat baru bisa terbit setelah DNS benar; percobaan yang gagal dihitung dalam batas laju (rate limit) Let's Encrypt.Atur domain panel (Settings → Domain panel)
Masuk sebagai owner, buka Settings → Domain panel, isi domain dashboard, domain API, dan email untuk Let's Encrypt, lalu Simpan & terapkan. Port 80/443 harus kosong di server. Panel menyalakan reverse proxy sendiri kalau belum jalan, menulis ulang override compose, dan me-recreate container web dan API, jadi halaman terputus beberapa detik. Atau lewat CLI:
aoox loginaoox domain set --web panel.example.com --api api.panel.example.com --acme-email kamu@example.comBuka https://panel.example.com
Sertifikat diminta saat host pertama kali diakses, jadi tunggu beberapa detik. Login lagi: sesi dari alamat IP tidak terbawa ke origin baru. Cek:
curl -I https://panel.example.comOpsional: hanya izinkan akses lewat domain
Setelah alamat HTTPS terbuka, aktifkan Hanya izinkan akses lewat domain di Settings → Domain panel (atau tambahkan
--domain-onlypada perintah di atas). Port 3000/3001 lalu hanya mendengarkan di127.0.0.1. Hapus aturan ufw yang kini tak berguna dan, kalau kamu membukanya, aturan firewall provider untuk 3000/3001:sudo ufw delete allow 3000/tcp sudo ufw delete allow 3001/tcp
IP:3000 juga tidak menjawab lagi. Cara memulihkan lewat SSH ada di Domain untuk panel. Domain juga bisa diberikan saat instalasi (--web-domain, --api-domain, --acme-email) kalau DNS sudah mengarah ke server, sehingga langkah di dashboard terlewati.11. Setelah instalasi
- Terminal. Instalasi baru sudah mengotorisasi key terminal untuk usermu, jadi buka menu Terminal. Hanya kalau instalasi mencetak
warning: terminal key not authorized automatically(atau Terminal menampilkan error autentikasi), pakai tombol owner Authorize automatically di Infrastruktur → Terminal access, atau jalankan perintah yang ditampilkan sebagai user yang sama. Detail di Web terminal. - Registry dan proxy. Aktifkan registry lokal sebelum deploy pertama dari repo Git. Reverse proxy dinyalakan otomatis saat kamu menyimpan domain panel.
- Backup panel. Atur Backup instance (Settings → Instance backup), dengan jadwal dan sebaiknya tujuan S3, dan unduh salinannya ke luar server. Restore butuh
ENCRYPTION_KEYyang sama, jadi simpan juga salinan privat/opt/aoox/.env.distdi tempat selain server ini. - Memperbarui.
aoox update panel --apply(atau Settings → Update aoox) menarik image baru dan me-restart stack;aoox updatememperbarui CLI-nya sendiri. Keduanya tidak pernah menulis ulang file compose atau menambah variabel baru ke.env.dist. Saat sebuah rilis membutuhkannya, jalankansudo aoox reinstall(coba--dry-rundulu): ia menulis ulang file compose, menggabungkan.env.disttanpa membuat ulang secret, dan me-recreate container tanpa menyentuh data. Lihat Update aoox dan aoox reinstall.
Kalau ada yang salah
| Gejala | Periksa |
|---|---|
Browser tidak bisa membuka IP:3000 | Firewall / security group provider (ufw tidak berpengaruh untuk port yang dipublikasikan Docker). Di server: sudo docker compose … ps. |
IP:80 / IP:443 tidak menjawab setelah instalasi | Wajar sampai domain panel pertama disimpan (langkah 10): reverse proxy belum berjalan. |
| Proxy tidak bisa bind 80/443 | Ada yang lain (Apache/nginx bawaan) memakainya: sudo ss -ltnp | grep -E ":(80|443) ", hentikan dan nonaktifkan. |
| Sertifikat tidak kunjung datang (sertifikat self-signed / default) | DNS belum menyebar, port 80 diblokir di provider, atau rate limit Let's Encrypt setelah gagal berulang. Coba dengan PROXY_ACME_STAGING=true. Lihat Jebakan umum. |
| Login berputar atau terminal bilang origin not allowed | WEB_ORIGIN berbeda dari alamat di browser. |
| Terminal: SSH authentication failed | TERMINAL_SSH_USER salah atau key belum diotorisasi. Lihat User SSH di VPS cloud. |
Selengkapnya di Troubleshooting.
Langkah berikutnya
Ada yang keliru? Edit halaman ini di GitHub ↗