$ aoox

DocsCLI

Mulai dengan CLI

aoox adalah CLI resmi aoox: menyimpan kredensial panel di mesinmu dan berbicara ke API yang sama dengan dashboard.

Perintah
aoox
Autentikasi
API token aoox_… dari panel
Butuh
Script installer (tanpa Node.js), atau Node.js 22+ (npm)
Tahap awal
CLI sudah bisa memasang aoox (install), masuk (login/whoami), dan build + deploy repo lokal (link/deploy). Perintah untuk project, database, log tail, dan lainnya belum ada — untuk itu pakai dashboard, webhook, atau panggil API langsung dengan token yang sama.

Memasang CLI

Di Linux atau macOS, script installer memasang aoox tanpa perlu Node.js sama sekali — tarball-nya membawa runtime Node sendiri:

Linux / macOS, tanpa Node.js
curl -fsSL https://aoox.dev/install-cli.sh | sh

aoox --version

Terpasang ke /usr/local/lib/aoox + /usr/local/bin/aoox (root/sudo), atau ~/.local/lib/aoox kalau tidak ada akses itu. Menjalankan ulang perintah yang sama berarti upgrade. Mendukung Linux (glibc — bukan Alpine/musl) dan macOS, x64 maupun arm64.

Windows, Alpine, atau sudah punya Node.js?
Pakai npm — butuh Node.js 22+ lebih dulu. Nanti, perbarui dengan aoox update.
Dari npm
npm install -g @hideandseeklab/aoox

aoox --version

Perintah terpasang sebagai aoox meski nama paketnya @hideandseeklab/aoox. Untuk ikut main sebelum dirilis, pasang dari source:

Dari source
git clone https://github.com/hideandseeklab/aoox-cli.git
cd aoox-cli
npm install
npm run build
npm link          # menyediakan perintah aoox secara global

aoox --version

Memasang aoox lewat aoox install

Perintah ini berbeda dari bagian sebelumnya: aoox install tidak menyambung ke panel yang sudah ada — ia memasang panelnya sendiri (postgres + api + web) di VPS Linux yang masih kosong, sebagai alternatif dari cara manual di Instalasi. Jalankan sebagai root, langsung di server tujuan.

Paling sederhana (tanpa domain, akses lewat IP)
$ sudo aoox install
==> Detecting the server public IP
Install aoox in /opt/aoox and run docker compose up -d? (Y/n)
==> Running docker compose up -d
==> Waiting for the API to be ready

aoox is installed in /opt/aoox.
Open: http://203.0.113.10:3000
Create the first owner account at /setup.
Dengan domain + HTTPS otomatis dan owner langsung dibuat
sudo aoox install \
  --web-domain panel.example.com \
  --api-domain api.panel.example.com \
  --acme-email saya@example.com \
  --admin-email saya@example.com \
  --admin-name "Admin" \
  --admin-password "kata-sandi-kuat" \
  --yes
  • Docker dipasang otomatis lewat get.docker.com bila belum ada — minta konfirmasi kecuali --yes.
  • --web-domain dan --api-domain harus dipakai bersamaan, dan keduanya butuh --acme-email untuk sertifikat Let's Encrypt lewat proxy bawaan.
  • Tanpa --admin-email, buat akun owner lewat /setup di browser seperti instalasi manual.
  • Folder instalasi default /opt/aoox (ubah dengan --dir); instalasi yang sudah ada di folder itu ditolak kecuali diberi --force.
  • --force pada instalasi yang sudah ada mencadangkan .env.dist dan file compose ke <dir>/backups/<timestamp>/ lalu memakai ulang secret yang ada beserta semua nilai yang sudah ada (hanya flag yang Anda berikan yang mengganti nilai), sehingga data tetap aman.
  • Memulai benar-benar dari nol butuh ketiganya: --force --new-secrets --wipe-data. Perintah ini menjalankan docker compose down -v untuk stack yang ada (volume database dihapus), membuat secret baru, dan meminta Anda mengetik folder instalasi sebagai konfirmasi — --yes saja tidak cukup; untuk mode non-interaktif pakai --confirm-wipe=/opt/aoox. --new-secrets atau --wipe-data sendirian ditolak: secret baru tidak bisa membuka volume database lama, dan itulah yang dulu merusak instalasi.
  • Secret (JWT_SECRET, ENCRYPTION_KEY, password Postgres) dibuat acak dan ditulis ke .env.dist dengan mode 0600 — tidak perluopenssl rand manual.
Perintah ini menjalankan ulang langkah-langkah di Instalasi secara otomatis: clone compose distribusi, isi env, docker compose up -d, lalu tunggu /auth/setup-status menjawab. Bukan penggantiaoox login — setelah panel terpasang, login seperti biasa untuk memakai aoox link/aoox deploy.

Masuk ke panel

  1. Buat API token di panel

    Settings → API token: beri nama (mis. laptop-saya), pilih kedaluwarsa, lalu salin token aoox_… yang hanya tampil sekali. Token bertindak sebagai pemiliknya dengan peran yang sama — lihat Keamanan akun. Dialog yang menampilkan token juga berisi baris aoox login --url … --token … yang siap disalin.

  2. Jalankan aoox login

    $ aoox login
    Use the address you open the dashboard with: your panel domain (e.g. https://dashboard.example.com),
    or http://<server-IP>:3000 if no panel domain is set yet.
    ? Dashboard URL https://panel.example.com
    Looking for the panel... ok
    API token (aoox_…) ********
    Verifying token... ok
    Logged in as kamu@example.com (owner) at https://panel.example.com
    Token saved to /home/kamu/.config/aoox/config.json

    Yang kamu isi hanya alamat dashboard — alamat yang kamu buka di browser, bukan alamat API. CLI membaca alamat API dari dashboard (/.well-known/aoox.json). Skema boleh dihilangkan: host tanpa skema dicoba lewat https lalu http, dan IP polos juga di port 3000, jadi 203.0.113.10 berfungsi pada instalasi baru tanpa domain panel. Bila dashboard tidak mengumumkan alamat API publik, CLI mengasumsikan <host yang sama>:3001 dan mengatakannya. Alamat API dari skrip lama tetap berfungsi (dengan satu baris catatan).

    Token diminta lewat prompt tersembunyi, bukan argumen, supaya tidak tertinggal di riwayat shell atau daftar proses. Sebelum disimpan, CLI memanggil GET /auth/me — kredensial yang ditolak tidak pernah ditulis ke disk.

  3. Pastikan tersambung

    $ aoox whoami
    kamu@example.com · owner · Admin
    Panel: https://panel.example.com

    Tambahkan --json untuk keluaran yang bisa diproses skrip; baris teks di atas otomatis disembunyikan.

Terhubung ke panel yang mana?

Menjalankan aoox tanpa argumen menampilkan daftar perintah dan, di bawahnya, ke mana CLI terhubung. Alamat dashboard dan API diambil dari login tersimpan (tanpa jaringan); baris registry meminta registry default ke panel dengan timeout singkat dan tidak pernah menggagalkan perintah. aoox --help dan aoox <perintah> --help tidak berubah.

$ aoox
...
Connected to
  Dashboard  https://dashboard.example.com
  API        https://api.example.com
  Registry   registry.example.com (self-hosted)

$ aoox            # belum login
Not connected — run: aoox login

Kalau registry tidak bisa dicek muncul Registry (could not check: panel unreachable); alamat registry localhost:… mendapat peringatan singkat untuk mengatur domain dengan aoox registry domain --set <host>.

aoox link menghubungkan folder repo ke satu aplikasi di panel, lalu aoox deploy membangun image di mesinmu, mem-push-nya ke registry, dan memicu deploy — mengikuti log sampai selesai seperti tab Deploy di dashboard.

  1. Link folder ke aplikasi

    $ cd repo-aplikasiku
    $ aoox link
    ? Select a project › toko
    ? Select an application › shop (shop)
    Linked: toko / shop (shop)
    Written to .aoox.json — safe to commit, contains no secrets.

    --project/--app melewati pemilihan interaktif — dipakai di CI. File .aoox.json yang dihasilkan tidak berisi token, aman masuk repo.

  2. Deploy

    $ aoox deploy
    ==> Build localhost:5000/toko/shop:a1b2c3d
    ==> docker login localhost:5000
    ==> Push localhost:5000/toko/shop:a1b2c3d
    ==> Updating the application & triggering a deploy
    [building] Building localhost:5000/toko/shop:a1b2c3d from https://…
    ...
    Deployed: localhost:5000/toko/shop:a1b2c3d

    Build berjalan di Docker lokal (docker build dengan --dockerfile/--context), lalu di-push ke registry aplikasi itu — default registry self-hosted bila ada lebih dari satu, pilih manual dengan --registry. Tag default git short SHA (+ -dirty bila ada perubahan belum di-commit); timpa dengan --tag.

Aplikasi otomatis dipindah ke sourceType: image memakai registry dan tag yang baru saja di-push — bukan mem-build ulang di server seperti build dari Git. Dua sumber aplikasi. Deploy yang masih berjalan untuk aplikasi yang sama ditolak (409) — tunggu selesai dulu.

Variabel (aoox env, aoox run)

aoox env membaca dan mengubah environment dari set variabel (yang sama dengan menu Variabel di dashboard) dan mengatur environment mana yang dipakai aplikasi tertaut. aoox run menjalankan perintah dengan variabel yang didapat aplikasi saat deploy, tanpa menulis file.

  • Environment set dipilih dengan --set <slug> (singkat -s) dan --env <nama> (-e).
  • Bawaan: --set adalah satu-satunya set yang dipakai aplikasi yang ditautkan dengan aoox link (atau satu-satunya set yang bisa kamu lihat); --env adalah satu-satunya environment set itu yang ditautkan. Bila ada beberapa kandidat, perintah berhenti dan menampilkan daftarnya — tidak pernah menebak. Tidak ada nama environment bawaan.
  • --app <id> memakai aplikasi lain, dan --stack <id> sebuah stack compose, sebagai ganti aplikasi tertaut.
Contoh sesi
$ aoox env list
backend  (Backend) · shared with shop, blog · your role: developer
  development             3 variables
  staging                 0 variables
  production (protected)  7 variables  used by 2

$ aoox env set API_URL=https://api.example.com GREETING="hello world" -s backend -e development
backend/development: added API_URL, GREETING (5 variables now)

$ aoox env list --set backend --env development            # hanya nama, nilai disamarkan
API_URL=••••••••
$ aoox env list --set backend --env development --reveal   # nilai (diaudit)
$ aoox env pull --set backend --env development            # menulis ./.env (mode 0600)
$ aoox env unset OLD_KEY --set backend --env development
$ aoox run -- npm run dev                                  # variabel aplikasi yang di-deploy (kemungkinan production)
Untuk kerja lokal, sertakan --set dan --env
Tanpa keduanya aoox run mereplikasi aplikasi tertaut seperti yang di-deploy, biasanya production. Lihat Pengembangan lokal.
PerintahFungsi
aoox env list [--set slug] [--env nama] [--reveal] [--json]Tanpa flag: semua set yang bisa kamu lihat, peranmu, pembagiannya, dan jumlah variabel tiap environment (juga sebagai aoox env sets). Dengan --set: satu set. Dengan --env: nama variabel environment itu; --reveal menampilkan nilainya lewat aksi reveal yang diaudit.
aoox env pull [--set slug] [--env nama] [--file .env] [--format dotenv|json|shell] [--force]Menulis variabel ke file dengan mode 0600 (hanya pemilik, bila OS mendukung). Tidak pernah menimpa file yang sudah ada kecuali dengan --force, dan memperingatkan sekali bila file tidak tercakup .gitignore (tidak pernah mengubah .gitignore sendiri).
aoox env set KEY=VALUE [KEY2=VALUE2 …] [--set slug] [--env nama] [--secret | --no-secret]Menambah atau mengubah variabel. Komentar (termasuk catatan) dan urutan baris yang ada dipertahankan; variabel baru ditaruh di akhir. --secret menandai variabel sebagai rahasia, --no-secret sebagai jelas bukan rahasia; tanpa keduanya, tandanya tetap (lihat Variabel rahasia). Nilai dengan ${{project.KEY}} ditolak: tulis ${{vars.KEY}}.
aoox env unset KEY [KEY2 …] [--set slug] [--env nama]Menghapus variabel; komentar dan baris lain tetap.
aoox env push --file .env [--set slug] [--env nama] [--yes]Mengganti seluruh environment dengan file lokal, setelah menampilkan variabel yang ditambah, diubah dan dihapus lalu meminta konfirmasi.
aoox env history [--set slug] [--env nama] [--limit 20] [--json]Riwayat versi sebuah environment, terbaru dulu: kapan, siapa, dan nama variabel yang ditambah (+), diubah (~) atau dihapus (-). Tidak pernah nilai.
aoox env diff --from nama --to nama [--set slug] [--json]Membandingkan dua environment dalam satu set menurut nama variabel: hanya di satu sisi, nilai berbeda, sama. Hanya mencetak nama.
aoox env promote --from nama --to nama [KEY …] [--all] [--yes] [--set slug]Menyalin variabel yang disebut (atau semuanya) beserta tanda rahasianya dari satu environment set ke environment lain, setelah menampilkan perubahannya dan meminta konfirmasi.
aoox env links [--app id | --stack id] [--json]Environment set yang dipakai aplikasi (atau stack), sesuai urutan penggabungan (1 = pertama, ditimpa yang berikutnya), beserta variabel yang ditimpa tautan berikutnya atau env sendiri.
aoox env link --set slug --env nama [--position n] [--app id | --stack id]Menautkan environment set. Ditaruh di akhir (jadi menang atas yang lain) kecuali --position (mulai dari 1) diberikan; environment yang sudah tertaut dipindah ke posisi itu. Berlaku pada deploy berikutnya.
aoox env unlink (--set slug --env nama | --position n) [--app id | --stack id]Melepas tautan. Berlaku pada deploy berikutnya.
aoox run [--set slug --env nama] [--file .env.local] [--quiet] [--app id | --stack id] -- perintah [argumen…]Menjalankan perintah dengan variabel di atas environment-mu saat ini (lihat di bawah). Tidak ada yang ditulis ke disk. Output langsung ke terminalmu, exit code perintah menjadi exit code aoox run, dan Ctrl+C atau SIGTERM diteruskan ke perintah.

Apa yang diteruskan aoox run ke perintah

  • Secara bawaan ia meniru yang dilakukan panel saat membuat container, sejauh yang bisa dilakukan dari terminal: membaca setiap environment set yang ditautkan aplikasi, berurutan (yang belakangan menang pada key yang sama), lalu menaruh env milik aplikasi di atasnya. Setiap pembacaan diaudit. Bila salah satunya tidak bisa dibaca (environment terlindungi, viewer, scope token), tidak ada yang dijalankan.
  • ${{vars.KEY}} diganti dengan nilai gabungan KEY dari set, satu tingkat seperti di panel.
  • Referensi ${{database.…}} dan ${{secret.…}}, serta ${{vars.KEY}} yang tidak didefinisikan set tertaut mana pun, dibiarkan apa adanya, dengan satu peringatan yang menyebut variabelnya: hanya panel yang meresolusinya saat deploy. Secret yang disinkronkan dari Infisical tidak ikut (ada peringatannya).
  • --set/--env memakai tepat satu environment set saja: tanpa tautan dan tanpa env sendiri.
  • --file .env.local berada di atas semua itu: urutannya, dari terendah ke tertinggi, environment-mu saat ini, lalu aoox, lalu file. File hanya dibaca, dan referensi di dalamnya tidak diresolusi.
Yang disuntikkan dan dari lapisan mana (dicetak ke standard error)
$ aoox run -- node server.js
aoox  Injecting 9 variables into your process · Application "shop-web": shared/production < backend/production < own env

Jumlahnya adalah yang ditambah atau ditimpa aoox, termasuk --file; variabel bawaan shell-mu tidak dihitung. Baris ini berwarna hanya di terminal: NO_COLOR mematikan warna, FORCE_COLOR memaksanya, dan pipe serta log CI tetap polos. --quiet (-q) menyembunyikan baris itu, tetapi peringatan tentang referensi yang tidak bisa diresolusi aoox selalu dicetak.

Format pull dan push

Format dan standard output
$ aoox env pull --env staging                        # ./.env, teks tersimpan beserta komentarnya
$ aoox env pull --format json                        # ./.env.json  {"KEY":"value"}
$ aoox env pull --format shell                       # ./.env.sh    export KEY='value'
$ aoox env pull --format json --file - | jq .PORT    # hanya ke standard output
$ eval "$(aoox env pull --format shell --file -)"    # muat ke shell saat ini
  • --file - menulis data ke standard output dan tidak ada yang lain di sana, jadi bisa di-pipe atau diberikan ke eval. Catatan (mis. soal referensi ${{…}}) dikirim ke standard error. Pada mode ini tidak ada pemeriksaan "file sudah ada" dan tidak ada peringatan .gitignore, karena tidak ada file yang ditulis.
  • Format shell membungkus tiap nilai dengan kutip tunggal dan menulis kutip tunggal di dalam nilai sebagai '\'', sehingga spasi, $ dan kutip selamat saat eval. Tanpa --file, filenya .env, .env.json atau .env.sh menurut format, selalu dengan mode 0600 bila OS mendukung.
Unggah file dan lihat hasilnya
$ aoox env push --file .env.staging --set backend --env staging
Environment: backend/staging
  + added (1): NEW_FLAG
  ~ changed (1): API_URL
  - removed (1): OLD_KEY
  = unchanged: 6
Variables that are not in the file are removed: this replaces the whole environment.
? Replace "backend/staging" with the contents of .env.staging? (y/N)
  • File diperiksa sebelum apa pun dikirim. Ditolak: nama tidak valid, awalan export , spasi di ujung baris, nama ganda, dan ${{project.…}}. Nilai ber-kutip (KEY="value") diterima dengan peringatan, karena panel menyimpan kutipnya sebagai bagian dari nilai. Akhir baris Windows dan BOM di awal dinormalkan.
  • push, promote dan diff tidak pernah mencetak nilai. push dan promote meminta konfirmasi; tanpa terminal (CI) keduanya menolak kecuali kamu memberi --yes. Bila orang lain mengubah environment di sela itu, tidak ada yang ditulis (409), sama seperti set.
  • Setiap perubahan tercatat sebagai versi (lihat riwayat dan restore); memulihkan versi lama dilakukan di dashboard.

Cara nilai disimpan (tanda kutip)

Panel menyimpan satu environment sebagai teks KEY=VALUE biasa, satu variabel per baris. Key adalah semua sebelum = pertama; nilainya adalah semua setelahnya, persis seperti yang diberikan. Tidak ada pemrosesan kutip atau escape — tidak di CLI, tidak di panel, tidak saat nilai dimasukkan ke container — jadi tanda kutip yang kamu ketik dihapus oleh shell-mu, dan kutip yang menjadi bagian nilai tetap menjadi bagiannya.

Yang kamu ketikNilai tersimpan
GREETING="hello world"hello world
QUERY=a=b=ca=b=c
MSG='say "hi" # not a comment'say "hi" # not a comment
EMPTY=nilai kosong
  • Ditolak sebelum apa pun dikirim: nama tidak valid (huruf, angka dan _, tidak diawali angka), nilai dengan baris baru (satu variabel per baris), dan nilai yang berakhir dengan spasi (panel memangkas ujung tiap baris).
  • Referensi ${{vars.KEY}} dan ${{database.<slug>.url}} disimpan dan di-pull apa adanya; panel meresolusinya saat container dibuat.
  • Stack compose membaca teks hasil resolusi lewat parser --env-file Docker Compose sendiri, yang menghapus kutip yang membungkus seluruh nilai. Hindari kutip pembungkus pada nilai yang dipakai stack.

Mengedit bersamaan

set, unset dan push membaca environment, mengubah teksnya, lalu menyimpannya kembali bersama versi yang dibaca. Bila orang lain menyimpan di sela itu (dashboard, terminal lain), panel menjawab 409 dan CLI mengatakan tidak ada yang ditulis — jalankan perintahnya lagi agar perubahanmu diterapkan di atas versi terbaru. Editor di dashboard bekerja dengan cara yang sama.

Siapa boleh apa

PeranEnvironment biasaEnvironment terlindungi (mis. production)
Owner / admin instanceSemuanyaSemuanya
Admin project, developerlist, pull, set, unset, push, promote, runHanya nama variabel. Selebihnya menampilkan error "backend/production" is protected; only instance owners and admins can read it.
ViewerHanya nama variabelHanya nama variabel
  • Tautan: env link/unlink butuh peran developer di project aplikasi itu; menambah atau melepas tautan ke environment terlindungi butuh peran admin project. Set harus dibagikan ke project itu.
  • Di CI buat API token lalu ekspor AOOX_TOKEN/AOOX_URL. Token bisa dibatasi ke sebagian environment set (Pengaturan → API token → batas variabel), mis. backend/staging, backend/* atau */development: environment lain ditolak dengan 403. Lihat Scope API token.
  • Token baca saja tetap bisa menjalankan aoox env pull, aoox env list --reveal dan aoox run (membaca tidak mengubah apa pun dan diaudit), tetapi set, unset, push, promote, link dan unlink ditolak. Viewer tidak pernah bisa membaca nilai, dengan atau tanpa token.
  • Setiap pembacaan nilai tercatat di audit log tanpa nilainya. CLI tidak pernah menyimpan environment di disk.
  • Membuat, membagikan, dan menghapus set serta environment dilakukan di dashboard oleh owner atau admin instance.

Pengembangan lokal

Jalankan aplikasi di laptop dengan variabel satu environment set, tanpa file .env dan tanpa menautkan folder. Cukup sudah masuk (login).

  1. Pasang CLI, buat token sempit, lalu masuk

    $ npm i -g @hideandseeklab/aoox
    $ aoox login

    Di panel, Pengaturan → API token → Buat token: aktifkan Read-only dan isi Batasi ke variabel dengan environment yang Anda pakai, mis. backend/development. Dengan begitu token di laptop tidak bisa menyentuh production. Lihat cakupan API token.

  2. Taruh perintahnya di package.json

    package.json
    "scripts": {
      "start:dev": "aoox run --set backend --env development -- nest start --watch"
    }

    Pindahan dari Infisical? infisical run --env=dev -- … menjadi aoox run --set <slug> --env development -- ….

  3. Selalu sertakan --set dan --env di lokal

    Tanpa keduanya, Anda mendapat variabel aplikasi yang sudah di-deploy
    aoox run -- … tanpa --set/--env butuh aplikasi tertaut dan menyuntikkan apa yang didapat kontainernya saat deploy: environment set yang tertaut ke aplikasi plus env miliknya sendiri. Itu biasanya production, dan mengubah tautan aplikasi di panel akan diam-diam mengubah apa yang didapat laptop Anda. Dengan --set/--env hanya satu environment yang disuntikkan: tanpa tautan, tanpa env aplikasi.
  4. Yang Anda lihat

    $ aoox run --set backend --env development -- nest start --watch
    aoox  Injecting 5 variables from backend/development (no links, no own env)
    • Baris itu keluar di standard error dan berwarna hanya di terminal (polos saat di-pipe atau dengan NO_COLOR). --quiet (-q) menyembunyikannya, tetapi tidak pernah peringatan.
    • Gagal dengan aman: kalau pembacaan ditolak (token salah, tidak punya akses, environment terproteksi, cakupan token), perintah tidak dijalankan sama sekali.
    • Variabel hanya ada di proses anak; tidak ada yang ditulis ke disk.
  5. Alat yang hanya membaca file

    $ aoox env pull --set backend --env development --file .env

    File ditulis dengan mode 0600 dan tidak ditimpa tanpa --force. Pastikan .env ada di .gitignore; aoox memperingatkan bila belum.

  6. Perlukah aoox link?

    Tidak untuk variabel lokal: --set/--env hanya butuh Anda sudah login. Anda memerlukannya untuk aoox deploy, untuk aoox run tanpa flag, dan untuk mengatur tautan lewat aoox env links/link/unlink. Perintah itu menulis .aoox.json (alamat panel, id dan nama project serta aplikasi, tanpa rahasia), aman untuk di-commit.

  7. CI

    Lewati aoox login dan isi AOOX_URL serta AOOX_TOKEN (variabel CI yang di-mask) dari token read-only yang dibatasi ke environment yang dibutuhkan job.

    $ AOOX_URL=https://panel.example.com aoox run --set backend --env development -- npm test

Batasan

  • Referensi ${{database.…}} dan ${{secret.…}} tetap apa adanya, dengan peringatan: hanya panel yang menyelesaikannya saat deploy. Arahkan variabel itu ke database lokal lewat variabel khusus lokal atau --file.
  • Secret yang disinkronkan dari Infisical tidak ikut.
  • Bila --set/--env dihilangkan dan kandidatnya banyak, perintah berhenti dan mendaftarkannya; tidak pernah menebak.

Build & push image (aoox registry)

Dua perintah untuk memasukkan image ke registry tanpa men-deploy-nya — berguna kalau image dipilih nanti di dashboard (Aplikasi baru → Image siap pakai). Keduanya tidak butuh aoox link; memakai login biasa (atau --url/--token). Registry default adalah yang self-hosted; pakai --registry <id> untuk yang lain.

$ aoox registry build myapp:1.0.0
==> Build registry.example.com/myapp:1.0.0
...
Built registry.example.com/myapp:1.0.0
Next: aoox registry push myapp:1.0.0 (or build with --push next time)

$ aoox registry push myapp:1.0.0
==> docker login registry.example.com
==> Push registry.example.com/myapp:1.0.0
Pushed registry.example.com/myapp:1.0.0
Use it in the dashboard: New application → Ready-made image

build membaca ./Dockerfile (-f/--dockerfile, --context) dan menamai image <host registry>/<nama>:<versi>. push hanya mendorong image yang sudah ada secara lokal dan menerima nama pendek maupun lengkap. Untuk build dan push sekaligus, pakai aoox registry build myapp:1.0.0 --push. Nama harus huruf kecil.

Tidak perlu mengetik semuanya. Kalau versinya dihilangkan (aoox registry build myapp) atau seluruh argumennya (aoox registry build), CLI membacanya dari proyek: konteks build untuk build, folder saat ini untuk push. nama:versi yang diketik selalu menang. File pertama yang ditemukan, dengan urutan ini, memberi tiap nilai:

UrutanSumberNamaVersi
1package.jsonname (scope dibuang: @acme/web jadi web)version
2pyproject.tomlname di [project] atau [tool.poetry]version (dilewati bila dynamic)
3Cargo.tomlname di [package]version di [package] (bukan versi workspace)
4composer.jsonname (vendor/pkg jadi pkg)version, bila ada
5pubspec.yamlnameversion
6*.csprojAssemblyName, atau nama fileVersion, atau VersionPrefix-VersionSuffix (hanya satu file)
7pom.xmlartifactId proyekversion proyek (bukan milik parent)
8VERSION—baris pertama yang tidak kosong
9tag git—tag tempat HEAD berada, tanpa awalan v
10nama foldernama folder, huruf kecil—

Nilai dari file yang tidak bisa dipakai (variabel $(…) atau ${…}, versi dynamic) dilewati dan sumber berikutnya dicoba. Nama diubah ke huruf kecil; tanda + pada versi (metadata build, tidak boleh ada di tag) menjadi _. Kalau HEAD sudah melewati tag git terakhir, tidak ada yang ditebak: beri tag rilisnya, ketik nama:versi, atau tambahkan --force untuk memakai bentuk git describe seperti 1.4.2-3-gabc1234.

$ aoox registry build
==> Image web:1.4.2 (name and version from package.json)
? Build web:1.4.2? (Y/n/e)

Karena nama atau versi turunan bisa saja keliru, CLI bertanya dulu sebelum melakukan apa pun: Y lanjut, n berhenti, e untuk mengetik nama:versi lain. --yes (-y) melewati pertanyaan. Tanpa terminal, atau saat CI terisi, CLI menolak dan meminta nama:versi atau --yes. nama:versi yang diketik lengkap tidak pernah ditanyakan. Kalau lupa menaikkan versi, pengecekan "already exists" di bawah tetap melindungi registry dan menunjukkan di mana mengubahnya.

Yang munculArtinya
error myapp:1.0.0 already exists in registry.example.com.Versi itu sudah ada di registry (dicek sebelum build dan sebelum push). Pilih versi baru — petunjuknya menyarankan yang berikutnya — atau tambahkan --force untuk menimpa. latest selalu boleh ditimpa.
error No local image myapp:1.0.0.push tidak pernah build. Jalankan aoox registry build myapp:1.0.0 dulu.
error A version is required: "myapp" has none.Versi tidak diketik dan tidak ditemukan di proyek. Tulis nama:versi, mis. aoox registry build myapp:1.0.0, atau isi versi di salah satu file pada daftar di atas.
Registry-nya localhost:5000Peringatan: alamat itu hanya bekerja di server itu sendiri. Beri registry domain dengan aoox registry domain --set registry.example.com.

Ganti domain panel

Alternatif dari Settings → Domain panel di dashboard — cocok untuk skrip provisioning. Lihat Domain untuk panel untuk detail apa yang terjadi di baliknya.

$ aoox domain set --web panel.example.com --api api.panel.example.com \
  --acme-email kamu@example.com
Domain saved: panel.example.com (dashboard), api.panel.example.com (API).
The panel will restart for a few seconds to apply it — the connection to this API will drop briefly.

Untuk membatalkannya, aoox domain clear menghapus domain dan kembali ke http://<IP server>:3000 (bertanya dulu; --yes melewati pertanyaan). Proxy dan domain aplikasi tidak disentuh. Lihat Menghapus domain.

Panel harus sudah punya INSTALL_DIR terisi di .env.dist (path absolut folder docker-compose.dist.yml di host itu) — tanpa itu perintah gagal dengan 400.

Update aoox

Ada dua hal berbeda yang diperbarui, dengan dua perintah. aoox update memperbarui CLI itu sendiri di komputermu; aoox update panel memperbarui panel (image aoox-api/aoox-web di server).

Arti aoox update berubah
Sebelum 0.1.0-alpha.8 aoox update mengecek panel. Perilaku lama sekarang jadi aoox update panel; menjalankan aoox update --apply mencetak Panel updates moved to: aoox update panel --apply dan keluar dengan error tanpa mengubah apa pun.

CLI: aoox update

Mencari versi terbaru di npm (tanpa login, tanpa panel). Semua dist-tag npm menjadi kandidat: instalasi pre-release ditawari versi terbaru apa pun labelnya (alpha, lalu beta, lalu rc), sedangkan instalasi stabil hanya melihat versi stabil dan tidak pernah pindah ke pre-release. Selama belum ada versi stabil, pre-release terbit di tag latest, sehingga npm i -g @hideandseeklab/aoox memasang yang terbaru. Kalau CLI dipasang lewat npm, ia menjalankan npm i -g @hideandseeklab/aoox@<versi> untukmu; untuk tarball standalone atau source checkout ia mencetak perintah persisnya alih-alih menebak.

$ aoox update --check
Update available: aoox CLI 0.1.0-rc.1 → 0.1.0-rc.2
Run: aoox update

$ aoox update
==> npm i -g @hideandseeklab/aoox@0.1.0-rc.2
Updated aoox CLI 0.1.0-rc.1 → 0.1.0-rc.2

$ aoox update
aoox CLI 0.1.0-rc.2 is up to date

Kalau registry npm tidak terjangkau, perintah gagal dengan pesan jelas (exit status bukan nol).

Panel: aoox update panel

Cek dan terapkan update untuk panel itu sendiri (bukan aplikasi yang di-deploy) — bandingkan digest image aoox-api/aoox-web di registry, bukan sekadar nomor versi.

$ aoox update panel
Running version: 0.1.0-rc.1
  api: hideandseeklab/aoox-api:latest (update available)
  web: hideandseeklab/aoox-web:latest (up to date)
Update available. Run with --apply to apply it.

$ aoox update panel --apply
Update applied — the panel will restart for a few seconds to apply it.

Bila instalasi di-pin ke tag versi (API_IMAGE / WEB_IMAGE di .env.dist), versi baru yang terbit tetap ditampilkan tetapi tidak pernah diterapkan oleh perintah ini: ia mencetak versi terbaru dan cara memindahkan pin (isi kedua variabel dengan tag baru, atau hapus agar mengikuti latest, lalu jalankan sudo aoox reinstall), dan --apply menolak alih-alih melaporkan berhasil.

Sama seperti aoox domain set, butuh INSTALL_DIR terisi. Lihat Memperbarui versi untuk cara manual lewat SSH sebagai alternatif.

Memperbaiki instalasi (aoox reinstall)

aoox update panel hanya pull + up -d: ia tidak menulis ulang docker-compose.dist.yml dan tidak menambah variabel baru ke .env.dist. Instalasi lama karena itu tidak menerima perbaikan yang butuh perubahan compose atau env (contoh nyata: Terminal error TERMINAL_SSH_USER is not set setelah update, karena instalasi lama tidak pernah menulis variabel itu). aoox reinstall memperbaikinya tanpa menyentuh data. Jalankan di server panel, sebagai root:

Lihat dulu apa yang akan berubah, lalu terapkan
$ sudo aoox reinstall --dry-run
$ sudo aoox reinstall
LangkahYang terjadi
Backup.env.dist dan file compose selalu disalin ke <dir>/backups/<waktu>/ sebelum ada yang berubah, juga saat tidak ada yang perlu diubah (.env.dist tetap izin 600).
Composedocker-compose.dist.yml (dan docker-compose.domain.yml bila ada) ditulis ulang dari salinan yang dibundel di CLI. docker-compose.override.yml milik fitur Domain panel/Environment tidak disentuh.
.env.distDigabung, bukan dibuat ulang: semua nilai, urutan, komentar, dan key tak dikenal dipertahankan; hanya key yang belum ada dan punya default aman yang ditambahkan (mis. TERMINAL_SSH_USER=root, INSTALL_DIR). POSTGRES_PASSWORD, JWT_SECRET, ENCRYPTION_KEY tidak pernah diubah — bila salah satunya hilang, perintah berhenti dengan pesan jelas.
Jalankan ulangdocker compose pull lalu up -d --force-recreate memakai daftar file compose yang sama dengan stack yang sedang berjalan. Volume (database) tidak disentuh. Lalu menunggu API sehat dan mencetak ringkasan.

Aman dijalankan berulang: bila tidak ada yang perlu diubah, tidak ada file yang ditulis ulang (folder backup tetap dibuat) dan container disegarkan. Bila docker-compose.override.yml memakai tag !override (opsi Hanya izinkan akses lewat domain) dan Docker Compose di host lebih lama dari 2.24.4, perintah berhenti sebelum mengubah apa pun: upgrade plugin Compose atau matikan opsi itu di dashboard dulu. Opsi: --dir (default /opt/aoox), --yes (tanpa konfirmasi), --no-pull, --terminal-ssh-user <user> (mengisi atau menimpa nilai itu), dan --dry-run (hanya cetak rencana).

Untuk memperbaiki instalasi yang berjalan, pakai aoox reinstall
aoox install --force dipakai untuk memasang ulang di atas folder yang sudah ada: perintah ini lebih dulu mencadangkan .env.dist dan file compose ke <dir>/backups/<timestamp>/, lalu mempertahankan secret dan nilai yang sudah ada, jadi data tetap terbaca. Untuk instalasi berjalan yang hanya perlu disegarkan, aoox reinstall tetap perintah yang tepat. Mulai dari nol butuh --force --new-secrets --wipe-data, yang menghapus seluruh data panel (lihat bagian memasang aoox lewat aoox install).

Tanpa CLI: edit .env.dist langsung (mis. tambah TERMINAL_SSH_USER=root) atau pakai halaman Environment di Settings, lalu docker compose … up -d.

Referensi perintah

PerintahFungsiFlag
aoox installMemasang aoox (postgres + api + web) di VPS baru lewat Docker Compose.--web-domain, --api-domain, --acme-email, --admin-email/-name/-password, --dir, --force, --new-secrets, --wipe-data, --confirm-wipe, --no-terminal-authorize, --terminal-ssh-user, --yes/-y
aoox loginMenyimpan alamat dashboard dan API token untuk perintah lain (alamat API ditemukan otomatis).--url/-u, --token/-t
aoox whoamiMenampilkan akun dan panel yang sedang dipakai.--url/-u, --token/-t, --json
aoox linkMenghubungkan folder repo ke sebuah aplikasi di panel (dipakai aoox deploy).--project, --app
aoox deployBuild image lokal, push ke registry, lalu deploy — mengikuti log sampai selesai.--tag, --dockerfile/-f, --context, --registry
aoox domain setSet domain kustom untuk panel itu sendiri (dashboard + API) tanpa SSH.--web, --api, --acme-email, --[no-]domain-only
aoox domain clearMenghapus domain kustom panel dan kembali ke akses lewat IP (IP:3000), setelah konfirmasi.--yes/-y
aoox registry domainSet atau hapus domain kustom untuk registry self-hosted.--set, --clear
aoox registry passwordMenampilkan alamat, username, dan password registry self-hosted (owner/admin), atau mereset password (owner) tanpa menyentuh image.--show, --reset, --yes/-y
aoox updateMemperbarui CLI aoox itu sendiri dari npm (menggantikan update panel yang lama — lihat aoox update panel).--check
aoox update panelCek atau terapkan update untuk panel aoox itu sendiri (aoox update yang lama).--apply
aoox registry buildBuild ./Dockerfile menjadi image lokal bernama registry; menolak versi yang sudah ada di sana. Dengan --push, image langsung dikirim juga.--push, --yes/-y, --registry, --dockerfile/-f, --context, --force
aoox env list | pull | push | set | unset | history | diff | promoteMenampilkan, mengunduh, mengunggah, membandingkan atau mengubah environment set variabel (lihat Variabel).--set/-s, --env/-e, --app, --stack, --url/-u, --token/-t; --reveal, --json (list); --file, --force, --format (pull); --file, --yes (push); --secret/--no-secret (set); --limit, --json (history); --from, --to (diff, promote); --all, --yes (promote)
aoox env links | link | unlinkMenampilkan atau mengubah urutan environment set yang dipakai aplikasi (atau --stack).--app, --stack; --set/-s, --env/-e, --position (link, unlink)
aoox run -- <perintah>Menjalankan perintah dengan variabel yang didapat aplikasi tertaut saat deploy (atau satu environment set), tanpa menulisnya ke disk.--set/-s, --env/-e, --app, --stack, --file, --quiet/-q, --url/-u, --token/-t
aoox registry pushPush image lokal yang sudah ada ke registry; menolak versi yang sudah ada di sana.--yes/-y, --registry, --force
aoox reinstallPerbaiki/segarkan instalasi panel yang ada tanpa kehilangan data (compose ditulis ulang, .env.dist digabung, pull + recreate).--dir, --dry-run, --yes, --no-pull, --terminal-ssh-user
aoox help [PERINTAH]Daftar perintah, atau bantuan satu perintah.—

Konfigurasi & variabel lingkungan

SumberIsiCatatan
config.json{ "url": "<api>", "webUrl": "<dashboard>", "token": "aoox_…" } di direktori konfigurasi oclif (~/.config/aoox/ di Linux).Ditulis dengan mode 0600; jalur lengkapnya dicetak saat login.
--url / --tokenMenimpa isi file untuk satu perintah. --url adalah alamat dashboard (alamat API tetap diterima).Berguna saat berpindah antar panel (produksi vs staging).
AOOX_URL / AOOX_TOKENSumber yang sama lewat environment.Dipakai CI; muncul juga di --help.
  • Urutan: flag → environment → isi config.json. Bila tidak ada yang lengkap, CLI menyuruh menjalankan aoox login.
  • Beberapa panel? Jangan login ulang bolak-balik — simpan satu sebagai default lalu timpa dengan --url/--token seperlunya.

Di CI (tanpa terminal)

aoox login butuh terminal interaktif. Di pipeline, lewati login dan berikan kredensial lewat environment:

.gitlab-ci.yml
deploy:
  image: node:20
  variables:
    AOOX_URL: https://panel.example.com
  script:
    - npx -p @hideandseeklab/aoox aoox whoami   # AOOX_TOKEN dari CI variable (masked)
Simpan token sebagai variabel CI yang masked, dan buat token terpisah per pipeline agar bisa dicabut tanpa mengganggu yang lain.

Di balik antivirus atau proxy perusahaan

Pemindaian HTTPS oleh antivirus (AVG, Avast, Kaspersky, ESET, Bitdefender) dan proxy perusahaan (Zscaler, Netskope, Fortinet, Palo Alto) menandatangani ulang lalu lintas HTTPS dengan sertifikat root mereka sendiri. Sertifikat itu terpasang di penyimpanan sertifikat sistem operasi Anda, tetapi Node hanya mengenal daftar bawaannya, jadi CLI dulu gagal dengan galat sertifikat padahal sertifikat panel sebenarnya baik-baik saja.

Pada Node 22.19+ atau 24.5+ CLI kini juga memercayai penyimpanan sistem selain daftar Node, sehingga langsung berfungsi tanpa pengaturan. Verifikasi sertifikat tidak pernah dimatikan. Pada Node yang lebih lama tidak ada yang berubah, dan pesan galat menyebut penerbit yang terlihat (misalnya AVG Web/Mail Shield Root).

  • Nonaktifkan penyimpanan sistem dengan AOOX_SYSTEM_CA=0.
  • NODE_EXTRA_CA_CERTS=/path/ke/root.pem tetap berfungsi bila Anda ingin memercayai satu root tertentu.
  • Node lama: setel NODE_OPTIONS=--use-system-ca (Node 22.15+ / 23.10+), perbarui Node, atau tambahkan domain panel ke pengecualian pemindaian HTTPS antivirus.

Jebakan umum

PesanPenyebab & solusi
The panel rejected the token (401)Token kedaluwarsa, dicabut, atau salah salin. Buat token baru di Settings → API token.
No interactive terminalBerjalan di CI/skrip. Beri --url dan --token, atau set AOOX_URL dan AOOX_TOKEN.
Cannot reach the panelAlamat salah atau panel tidak terjangkau dari mesin ini. Pakai alamat yang kamu buka untuk dashboard, periksa firewall / security group, atau pasang domain panel (Infrastructure → Panel domain). Uji dengan curl <url-dashboard>/.well-known/aoox.json.
… answers plain HTTPKamu memakai https:// di port yang berbicara HTTP biasa (mis. :3000). Pakai alamat http://, atau pasang domain panel untuk mendapat HTTPS.
Your aoox CLI is older than the panelPeringatan, bukan error. Perbarui dengan aoox update.
Config is corrupt (not valid JSON)File konfigurasi teredit manual. Hapus file itu lalu aoox login lagi.
403 pada perintah tertentuPeran akun pemilik token tidak cukup — token tidak menambah hak apa pun di atas pemiliknya. Bila tokennya punya scope, lihat token read-only/project-limited.
This repo is not linked yetaoox deploy dijalankan sebelum aoox link. Jalankan aoox link dulu di folder repo.
A deployment is already running for this application (409)Aplikasi yang sama sedang di-deploy — dari dashboard, webhook, atau aoox deploy lain. Tunggu selesai, cek tab Deploy.
aoox install: Root is requiredJalankan dengan sudo — instalasi menulis ke path sistem dan mengelola Docker.
aoox install: An installation already exists in …Folder --dir (default /opt/aoox) sudah terisi. Untuk memperbaiki instalasi itu, pakai aoox reinstall. --force memasang ulang di atasnya sambil mempertahankan data dan secret (file sebelumnya dicadangkan ke <dir>/backups/), atau pakai --dir lain. Instalasi dari nol yang menghapus semua data butuh --force --new-secrets --wipe-data.
Belum tersedia
Perintah untuk project, log tail mandiri, dan database; paket npm resmi; autocomplete shell; keluaran --json untuk semua perintah (baru whoami).

Langkah berikutnya

Ada yang keliru? Edit halaman ini di GitHub ↗