Browse Source
Add AI-Agent-Standards templates, Zammad/Mailcow dual-domain docs, Ollama and Mikrotik VM audits with config backup, PC-Multimedia bootstrap, geonet-console Zammad/AI chat integration, and workspace registry updates. Co-authored-by: Cursor <cursoragent@cursor.com>master
253 changed files with 13069 additions and 450 deletions
@ -0,0 +1,182 @@
@@ -0,0 +1,182 @@
|
||||
# AI Agent Documentation Standards |
||||
|
||||
Standar **Project Knowledge Preservation** untuk monorepo, dioptimalkan agar agent berikutnya lanjut kerja dengan **token minimal** (< 2000 token cold start). |
||||
|
||||
--- |
||||
|
||||
## Struktur |
||||
|
||||
``` |
||||
AI-Agent-Standards/ |
||||
├── README.md |
||||
├── recommendations.md |
||||
├── cursor-rule-project-handover.mdc |
||||
├── prompts/ |
||||
│ ├── end-of-session-handover.md |
||||
│ └── generate-ai-session-summary.md |
||||
├── templates/ |
||||
│ ├── handover-checklist.md |
||||
│ ├── repo/ |
||||
│ │ ├── AGENTS.md <- cold start (copy ke ROOT project) |
||||
│ │ ├── context-index.md <- peta domain (on-demand, boleh tebal) |
||||
│ │ ├── ai-session-summary.md <- rolling memory (max 80 baris) |
||||
│ │ ├── project-status.md |
||||
│ │ ├── todo.md |
||||
│ │ ├── changelog.md |
||||
│ │ ├── version.md |
||||
│ │ ├── server.md <- host/IP, docker, nginx, DB |
||||
│ │ ├── issues.md |
||||
│ │ ├── adr-template.md |
||||
│ │ ├── api/README.md |
||||
│ │ └── guide/README.md |
||||
│ └── workspace/ |
||||
└── examples/ |
||||
``` |
||||
|
||||
--- |
||||
|
||||
## Cold start (paling penting) |
||||
|
||||
``` |
||||
Workspace-Session.md (Active focus) # jika multi-project |
||||
-> {project}/AGENTS.md # ~200-400 token |
||||
-> {project}/docs/ai-session-summary.md # TL;DR + Lanjut + Jangan |
||||
-> STOP - mulai kerja |
||||
``` |
||||
|
||||
On-demand saja: todo, issues, api, guide, server.md, context-index, adr. |
||||
|
||||
**Jangan cold-start:** changelog penuh, version history, WORKLOG, development-log. |
||||
|
||||
**Rolling session memory = hanya** `docs/ai-session-summary.md`. |
||||
File kronologis lain = arsip. |
||||
|
||||
--- |
||||
|
||||
## Read budget |
||||
|
||||
| Tujuan | Baca maksimal | |
||||
|--------|----------------| |
||||
| Lanjut task yang sama | AGENTS + ai-session-summary | |
||||
| Ambil task baru | + todo.md (High) | |
||||
| Debug | + issues.md (ID terkait) | |
||||
| Deploy / koneksi / infra | + docs/server.md | |
||||
| Ubah API | + docs/api/ | |
||||
| Flow / prosedur | + docs/guide/ | |
||||
| Arsitektur | + docs/adr/ | |
||||
| Navigasi domain | + context-index (Zona B) | |
||||
|
||||
--- |
||||
|
||||
## Batas keras tulis |
||||
|
||||
| File | Batas | |
||||
|------|-------| |
||||
| `AGENTS.md` | ~40 baris | |
||||
| `ai-session-summary.md` | **80 baris / ~1500 token**; wajib TL;DR + Lanjut + Jangan | |
||||
| `Workspace-Session.md` | ~50-100 baris; wajib Active focus | |
||||
|
||||
--- |
||||
|
||||
## Struktur per subproject |
||||
|
||||
``` |
||||
{project}/ |
||||
├── AGENTS.md # WAJIB - cold start (root project) |
||||
├── .env.example # template URL/env (wajib) |
||||
└── docs/ |
||||
├── ai-session-summary.md # rolling memory (OVERWRITE) |
||||
├── context-index.md # peta (Zona A pointers + Zona B on-demand) |
||||
├── project-status.md |
||||
├── todo.md |
||||
├── changelog.md |
||||
├── version.md |
||||
├── server.md # host/IP, runtime, DB (wajib) |
||||
├── system-requirements.md # OS, runtime, tool (wajib) |
||||
├── issues.md |
||||
├── adr/ |
||||
├── api/ # jika API / framework API |
||||
└── guide/ # wajib migration.md + guide lain |
||||
``` |
||||
|
||||
--- |
||||
|
||||
## Tier handover |
||||
|
||||
| Tier | Kapan | File | |
||||
|------|-------|------| |
||||
| **1 Minimal** | Perubahan kode/config | session (TL;DR) + todo + changelog + version (+ AGENTS jika perlu) | |
||||
| **Deploy** | Install ke device/server, rilis APK/binary, cutover prod | **Wajib** append `version.md` (bullet poin) + bump versi build config | |
||||
| **2 Relevan** | Kondisi terpenuhi | issues, adr, guide, server.md, system-requirements, .env.example, migration, status, context-index, api | |
||||
| **3 Monorepo** | Multi-project | Workspace-Session (Active focus) | |
||||
|
||||
--- |
||||
|
||||
## Single owner |
||||
|
||||
| Informasi | Owner | |
||||
|-----------|-------| |
||||
| Cold start / aturan kritis | `AGENTS.md` | |
||||
| Narasi sesi (rolling) | `ai-session-summary.md` | |
||||
| Priority | `todo.md` | |
||||
| Bug / RCA | `issues.md` | |
||||
| Changelog | `changelog.md` | |
||||
| Poin versi | `version.md` — **wajib append setiap deploy/naik versi** | |
||||
| API | `docs/api/` | |
||||
| Flow prosedur | `docs/guide/` | |
||||
| Server / IP / runtime / DB | `docs/server.md` | |
||||
| System requirements | `docs/system-requirements.md` | |
||||
| URL/env template | `.env.example` | |
||||
| Migrasi server/domain | `docs/guide/migration.md` | |
||||
| Peta domain | `context-index.md` | |
||||
| Lintas project | `Workspace-Session.md` | |
||||
|
||||
Pengetahuan penting, arsitektur, flow, inventori server, system requirements, migrasi **tidak boleh** hanya di chat. **No hardcoded URL.** |
||||
|
||||
--- |
||||
|
||||
## Setup subproject baru |
||||
|
||||
1. Copy `templates/repo/AGENTS.md` ke **root** project (sibling `docs/`) |
||||
2. Copy sisa `templates/repo/*` ke `{project}/docs/` |
||||
3. Isi AGENTS.md (pendek) dan context-index Zona A |
||||
4. Daftarkan di `Workspace-Context.md` |
||||
|
||||
## Quick command |
||||
|
||||
``` |
||||
Lakukan Project Knowledge Preservation sesuai standar di |
||||
AI-Agent-Standards/prompts/end-of-session-handover.md |
||||
``` |
||||
|
||||
## Cursor |
||||
|
||||
Salin `cursor-rule-project-handover.mdc` ke `.cursor/rules/` |
||||
|
||||
--- |
||||
|
||||
## No hardcoded URL |
||||
|
||||
- Semua URL/domain/host dari `.env` / env var / BuildConfig |
||||
- Template commit: `.env.example`; secret hanya di `.env` lokal (gitignore) |
||||
- Migrasi: update .env.example, server.md, guide/migration.md`r |
||||
|
||||
## Bootstrap project baru (salin ke agent) |
||||
|
||||
Prompt siap pakai: [prompts/bootstrap-new-project.md](prompts/bootstrap-new-project.md) |
||||
|
||||
Agent akan membaca template lalu membuat AGENTS.md + docs/ untuk satu atau lebih subproject, dan mendaftarkannya di Workspace-Context.md. |
||||
|
||||
Contoh: |
||||
|
||||
``` |
||||
Ikuti AI-Agent-Standards/prompts/bootstrap-new-project.md |
||||
|
||||
projects: |
||||
- path: lagercloud.com/billing |
||||
name: Billing |
||||
description: Service tagihan |
||||
stack: Python FastAPI |
||||
type: api |
||||
has_api: true |
||||
``` |
||||
@ -0,0 +1,70 @@
@@ -0,0 +1,70 @@
|
||||
--- |
||||
description: Wajib jalankan Project Knowledge Preservation di akhir sesi atau sebelum commit/push |
||||
alwaysApply: true |
||||
--- |
||||
|
||||
# End of Session - Project Handover |
||||
|
||||
Sebelum menganggap pekerjaan selesai atau melakukan commit/push: |
||||
|
||||
1. Jalankan **Project Knowledge Preservation** sesuai standar |
||||
2. Standar lengkap: `AI-Agent-Standards/prompts/end-of-session-handover.md` |
||||
|
||||
## Tier (ringkas) |
||||
|
||||
**Tier 1 - Minimal** (per project yang berubah): |
||||
- OVERWRITE `docs/ai-session-summary.md` (max 80 baris; TL;DR + Lanjut + Jangan) |
||||
- UPDATE `docs/todo.md` ("Selesai sesi ini" overwrite) |
||||
- APPEND `docs/changelog.md` + `docs/version.md` (**wajib** jika deploy/naik versi — poin-poin perubahan, jangan skip) |
||||
- UPDATE `AGENTS.md` hanya jika aturan kritis berubah |
||||
|
||||
## Deploy / naik versi (wajib) |
||||
|
||||
Perubahan yang di-install ke device, server, atau production: |
||||
1. Bump versi di build config (SSOT numerik) |
||||
2. Append `docs/version.md` — bullet: apa berubah, fix/feature, QC/deploy note |
||||
3. Append `docs/changelog.md` (Keep a Changelog) |
||||
4. Tier 1 session summary + todo |
||||
|
||||
**Tier 2 - Jika relevan:** issues, ADR, guide, server.md, system-requirements.md, .env.example, guide/migration.md, project-status, context-index, api/ |
||||
|
||||
**Tier 3 - Monorepo:** OVERWRITE `Workspace-Session.md` (Active focus) |
||||
|
||||
## Single Owner |
||||
|
||||
- Cold start -> `AGENTS.md` |
||||
- Priority -> `todo.md` |
||||
- Bug/RCA -> `issues.md` |
||||
- Narasi sesi -> `ai-session-summary.md` |
||||
- Server/IP/DB -> `docs/server.md` |
||||
- System requirements -> `docs/system-requirements.md` |
||||
- Migrasi domain/server -> `docs/guide/migration.md` + `.env.example` |
||||
- Template URL/env -> `.env.example` (root project) |
||||
- Flow prosedur -> `docs/guide/` |
||||
- Arsitektur -> `docs/adr/` |
||||
|
||||
## No hardcoded URL |
||||
|
||||
- URL/domain/host:port dari env / `.env` / BuildConfig — **bukan** hardcode di source |
||||
- Migrasi: update `.env.example`, server.md, migration.md — minimal ubah kode |
||||
- Commit `.env.example` OK; `.env` dengan secret **tidak** |
||||
|
||||
## Aturan |
||||
|
||||
- Jangan simpan pengetahuan penting hanya di chat |
||||
- Jangan commit secret/credential |
||||
- Final Report ke user |
||||
|
||||
## Urutan Baca AI Berikutnya |
||||
|
||||
``` |
||||
Workspace-Session (Active focus) -> AGENTS.md -> ai-session-summary (TL;DR) -> STOP |
||||
``` |
||||
|
||||
On-demand: todo, issues, api, guide, server.md, system-requirements, migration, context-index, adr. |
||||
|
||||
## Slash Commands |
||||
|
||||
- `/handover` - full tiered preservation |
||||
- `/session-summary` - hanya ai-session-summary.md |
||||
- `/workspace-summary` - hanya Workspace-Session.md |
||||
@ -0,0 +1,56 @@
@@ -0,0 +1,56 @@
|
||||
# AI Session Summary |
||||
|
||||
<!-- CONTOH - max 80 baris, omit-if-N/A --> |
||||
|
||||
```yaml |
||||
session: 2026-07-03-ldap-login-fix |
||||
project: lagercloud.com/ldap |
||||
version: 1.2.0 |
||||
status: ready |
||||
next: Token revocation on logout |
||||
previous: 2026-07-01-ldap-migration |
||||
agent: Cursor |
||||
branch: feat/jwt-refresh |
||||
``` |
||||
|
||||
--- |
||||
|
||||
## TL;DR |
||||
|
||||
- Tambah endpoint JWT refresh token |
||||
- Perbaiki 401 loop saat token expired |
||||
- Update docs API auth |
||||
|
||||
--- |
||||
|
||||
## Lanjut dari sini |
||||
|
||||
1. Token revocation on logout |
||||
2. Integrasi refresh ke client Super App |
||||
|
||||
> Backlog: [todo.md](./todo.md) |
||||
|
||||
--- |
||||
|
||||
## Jangan |
||||
|
||||
- Jangan simpan refresh token di localStorage (pakai httpOnly cookie) |
||||
- Jangan revert error code TOKEN_EXPIRED di middleware |
||||
|
||||
--- |
||||
|
||||
## Detail |
||||
|
||||
### Bug fix |
||||
|
||||
| Bug | Root cause | Fix | Ref | |
||||
|-----|------------|-----|-----| |
||||
| 401 loop | Middleware throw unhandled | Return 401 + TOKEN_EXPIRED | [ISS-001](./issues.md) | |
||||
|
||||
### API |
||||
|
||||
| Method | Endpoint | Perubahan | |
||||
|--------|----------|-----------| |
||||
| POST | `/api/v1/auth/refresh` | Baru | |
||||
|
||||
**On-demand:** [../AGENTS.md](../AGENTS.md) | [todo.md](./todo.md) | [api/](./api/) |
||||
@ -0,0 +1,58 @@
@@ -0,0 +1,58 @@
|
||||
# Workspace Session |
||||
|
||||
<!-- CONTOH monorepo --> |
||||
|
||||
## Active focus |
||||
|
||||
- `lagercloud.com/ldap`: JWT refresh live -> next: token revocation |
||||
- `lagercloud.com/infra`: heartbeat 60s -> next: retry logic |
||||
- `lagercloud.com/Kotlin`: spec Device Request -> next: implement poll |
||||
|
||||
--- |
||||
|
||||
## Session Information |
||||
|
||||
| Field | Value | |
||||
|-------|-------| |
||||
| Tanggal | 2026-07-03 | |
||||
| Session ID | 2026-07-03-auth-agent-device | |
||||
| AI Agent | Cursor | |
||||
|
||||
--- |
||||
|
||||
## Executive Summary |
||||
|
||||
- LDAP: JWT refresh token |
||||
- infra: heartbeat timeout 60s |
||||
- Kotlin: spec Device Request |
||||
|
||||
--- |
||||
|
||||
## Project yang dikerjakan |
||||
|
||||
| Project | Path | Summary | Branch | Version | |
||||
|---------|------|---------|--------|---------| |
||||
| ldap | `lagercloud.com/ldap` | JWT refresh | feat/jwt-refresh | 1.2.0 | |
||||
| infra | `lagercloud.com/infra` | Heartbeat 60s | fix/heartbeat | 0.4.1 | |
||||
| Kotlin | `lagercloud.com/Kotlin` | Spec Device Request | docs/device-request | 1.1.2 | |
||||
|
||||
--- |
||||
|
||||
## Cross-Project Impact |
||||
|
||||
| Perubahan | Project | Dampak | |
||||
|-----------|---------|--------| |
||||
| JWT refresh | ldap | Client/agent perlu update auth | |
||||
| Heartbeat 60s | infra | Kotlin agent polling disesuaikan | |
||||
|
||||
--- |
||||
|
||||
## Referensi detail (on-demand) |
||||
|
||||
| Project | Cold start | Session | Version | |
||||
|---------|------------|---------|---------| |
||||
| ldap | [AGENTS.md](../lagercloud.com/ldap/AGENTS.md) | [session](../lagercloud.com/ldap/docs/ai-session-summary.md) | [version](../lagercloud.com/ldap/docs/version.md) | |
||||
| infra | [AGENTS.md](../lagercloud.com/infra/AGENTS.md) | [session](../lagercloud.com/infra/docs/ai-session-summary.md) | [version](../lagercloud.com/infra/docs/version.md) | |
||||
| Kotlin | [AGENTS.md](../lagercloud.com/Kotlin/AGENTS.md) | [session](../lagercloud.com/Kotlin/docs/ai-session-summary.md) | [version](../lagercloud.com/Kotlin/docs/version.md) | |
||||
|
||||
**Konteks stabil:** [Workspace-Context.md](../Workspace-Context.md) |
||||
@ -0,0 +1,358 @@
@@ -0,0 +1,358 @@
|
||||
# Prompt: Bootstrap Project Docs dari AI-Agent-Standards |
||||
|
||||
> **Cara pakai:** Salin seluruh isi file ini ke chat agent, lalu isi blok **INPUT** di bawah (atau sebutkan path/nama project di pesan Anda). |
||||
> **Alias:** `/bootstrap-docs` |
||||
> **Tujuan:** Agent membaca template di `AI-Agent-Standards/` lalu **membuat** struktur dokumentasi standar untuk satu atau lebih subproject baru di monorepo. |
||||
|
||||
--- |
||||
|
||||
## INPUT (isi sebelum / saat menjalankan) |
||||
|
||||
Salin dan lengkapi: |
||||
|
||||
```yaml |
||||
projects: |
||||
- path: {path/relatif/dari/root monorepo} # contoh: lagercloud.com/my-service |
||||
name: {Nama Project} |
||||
description: {1-2 kalimat} |
||||
stack: {tech stack singkat} |
||||
type: app | api | library | infra | docs-only |
||||
has_api: true | false # true => buat docs/api/ |
||||
has_guide: true | false # true => buat docs/guide/ |
||||
version: 0.1.0 |
||||
servers: # opsional; wajib diisi jika sudah diketahui |
||||
- host: "{IP atau hostname}" |
||||
env: dev|staging|prod |
||||
role: app|db|reverse-proxy|worker |
||||
apps: # docker, nginx, IIS, Apache, SQL Server, PostgreSQL, ... |
||||
- name: "{service}" |
||||
kind: Docker|nginx|IIS|Apache|SQL Server|PostgreSQL|other |
||||
port: "{port}" |
||||
path_or_container: "{compose service / site / instance}" |
||||
critical_rules: # 3-7 bullet |
||||
- "{aturan kritis 1}" |
||||
- "{aturan kritis 2}" |
||||
initial_todos: # opsional |
||||
- priority: High |
||||
item: "{task}" |
||||
``` |
||||
|
||||
Jika user hanya memberi daftar path tanpa YAML, tanyakan field yang kurang **sekali**, lalu lanjut. Jangan tanya berulang. |
||||
|
||||
**Asumsi default jika tidak disebut:** |
||||
- `type: app` |
||||
- `has_api: false` (kecuali type = api atau nama/deskripsi menyebut API) |
||||
- `has_guide: false` |
||||
- `version: 0.1.0` |
||||
- `critical_rules`: minimal "No commit kecuali user minta", "No hardcoded URL/domain/IP — pakai .env.example", "Jangan commit .env", "Pengetahuan penting wajib ke docs bukan hanya chat" |
||||
|
||||
--- |
||||
|
||||
## Objective |
||||
|
||||
Untuk **setiap** project di INPUT: |
||||
|
||||
1. Baca template dari `AI-Agent-Standards/templates/repo/` |
||||
2. Buat struktur file sesuai standar |
||||
3. Isi field wajib (bukan meninggalkan semua placeholder `{...}`) |
||||
4. Daftarkan project di `Workspace-Context.md` (root monorepo) |
||||
5. Laporkan hasil ke user |
||||
|
||||
**Jangan** commit/push kecuali user meminta. |
||||
**Jangan** menimpa file yang sudah ada tanpa konfirmasi (kecuali user bilang "overwrite"). |
||||
|
||||
--- |
||||
|
||||
## Sumber template (WAJIB dibaca dulu) |
||||
|
||||
Baca file berikut sebelum menulis (cukup file ini + template yang akan di-copy): |
||||
|
||||
| File | Kegunaan | |
||||
|------|----------| |
||||
| `AI-Agent-Standards/README.md` | Ringkasan standar | |
||||
| `AI-Agent-Standards/templates/repo/AGENTS.md` | Cold start (ke ROOT project) | |
||||
| `AI-Agent-Standards/templates/repo/ai-session-summary.md` | Rolling session memory | |
||||
| `AI-Agent-Standards/templates/repo/context-index.md` | Peta domain | |
||||
| `AI-Agent-Standards/templates/repo/todo.md` | Priority | |
||||
| `AI-Agent-Standards/templates/repo/changelog.md` | Keep a Changelog | |
||||
| `AI-Agent-Standards/templates/repo/version.md` | Poin versi | |
||||
| `AI-Agent-Standards/templates/repo/issues.md` | Issues | |
||||
| `AI-Agent-Standards/templates/repo/project-status.md` | Status | |
||||
| `AI-Agent-Standards/templates/repo/adr-template.md` | ADR template | |
||||
| `AI-Agent-Standards/templates/repo/api/README.md` | Hanya jika has_api | |
||||
| `AI-Agent-Standards/templates/repo/guide/README.md` | Hanya jika has_guide | |
||||
| `AI-Agent-Standards/templates/repo/server.md` | Inventori server (selalu dibuat) | |
||||
| `templates/repo/system-requirements.md` | System requirements (selalu dibuat) | |
||||
| `templates/repo/.env.example` | Template URL/env (selalu dibuat) | |
||||
| `templates/repo/guide/migration.md` | Migrasi server/domain (selalu dibuat) | |
||||
| `Workspace-Context.md` | Daftarkan project + indeks server | |
||||
|
||||
Encoding: tulis file sebagai **UTF-8** (tanpa UTF-16). |
||||
|
||||
--- |
||||
|
||||
## Struktur yang harus dibuat (per project) |
||||
|
||||
``` |
||||
{path}/ |
||||
├── AGENTS.md # cold start |
||||
├── .env.example # template URL/env (WAJIB, commit OK) |
||||
└── docs/ |
||||
├── ai-session-summary.md |
||||
├── context-index.md |
||||
├── project-status.md |
||||
├── todo.md |
||||
├── changelog.md |
||||
├── version.md |
||||
├── issues.md |
||||
├── adr/ |
||||
│ └── 000-template.md # dari adr-template.md |
||||
├── server.md # WAJIB - inventori host/IP/runtime/DB |
||||
├── system-requirements.md # WAJIB - OS, runtime, tool minimum |
||||
├── api/ # HANYA jika has_api: true |
||||
│ └── README.md |
||||
└── guide/ # WAJIB (minimal migration.md) |
||||
├── README.md |
||||
└── migration.md # migrasi server/domain |
||||
``` |
||||
|
||||
### Mapping copy |
||||
|
||||
| Sumber (`AI-Agent-Standards/templates/repo/`) | Tujuan | |
||||
|-----------------------------------------------|--------| |
||||
| `AGENTS.md` | `{path}/AGENTS.md` | |
||||
| `ai-session-summary.md` | `{path}/docs/ai-session-summary.md` | |
||||
| `context-index.md` | `{path}/docs/context-index.md` | |
||||
| `project-status.md` | `{path}/docs/project-status.md` | |
||||
| `todo.md` | `{path}/docs/todo.md` | |
||||
| `changelog.md` | `{path}/docs/changelog.md` | |
||||
| `version.md` | `{path}/docs/version.md` | |
||||
| `issues.md` | `{path}/docs/issues.md` | |
||||
| `server.md` | `{path}/docs/server.md` | |
||||
| `system-requirements.md` | `{path}/docs/system-requirements.md` | |
||||
| `.env.example` | `{path}/.env.example` | |
||||
| `guide/migration.md` | `{path}/docs/guide/migration.md` | |
||||
| `adr-template.md` | `{path}/docs/adr/000-template.md` | |
||||
| `api/README.md` | `{path}/docs/api/README.md` (jika has_api) | |
||||
| `guide/README.md` | `{path}/docs/guide/README.md` | |
||||
|
||||
--- |
||||
|
||||
## Isi wajib (ganti placeholder) |
||||
|
||||
### 1. `{path}/AGENTS.md` (max ~40 baris) |
||||
|
||||
- Project path monorepo |
||||
- **Apa ini?** = `description` |
||||
- **Aturan kritis** = `critical_rules` (+ default jika kurang dari 3) |
||||
- Sertakan aturan **no hardcoded URL** + link `.env.example`, `docs/system-requirements.md`, `docs/guide/migration.md` |
||||
- Pertahankan urutan baca stop-early dari template |
||||
|
||||
### 2. `{path}/docs/context-index.md` |
||||
|
||||
**Zona A** wajib diisi: |
||||
- Nama, path, deskripsi/stack, tipe, versi, link AGENTS + session + todo |
||||
- Last updated = tanggal hari ini |
||||
|
||||
**Zona B:** biarkan tabel kosong atau minimal; hapus baris api/guide jika `has_api`/`has_guide` false. |
||||
|
||||
### 3. `{path}/docs/ai-session-summary.md` (max 80 baris) |
||||
|
||||
Isi sesi init: |
||||
|
||||
```yaml |
||||
session: {YYYY-MM-DD}-init |
||||
project: {path} |
||||
version: {version} |
||||
status: ready |
||||
next: {item High pertama dari initial_todos, atau "Isi todo dan mulai implementasi"} |
||||
agent: {nama agent jika diketahui, else Unknown} |
||||
branch: main |
||||
``` |
||||
|
||||
**TL;DR:** |
||||
- Bootstrap dokumentasi standar AI-Agent-Standards |
||||
- Project `{name}` siap dilanjutkan agent berikutnya |
||||
|
||||
**Lanjut dari sini:** |
||||
1. {dari initial_todos High, atau "Lengkapi spesifikasi / implementasi"} |
||||
|
||||
**Jangan:** |
||||
- Jangan simpan pengetahuan penting hanya di chat |
||||
- Jangan commit secret |
||||
|
||||
Hapus blok Detail jika tidak perlu. |
||||
|
||||
### 4. `{path}/docs/version.md` |
||||
|
||||
Entri pertama: |
||||
|
||||
```markdown |
||||
## [{version}] - {YYYY-MM-DD} |
||||
|
||||
- Bootstrap dokumentasi standar (AGENTS.md + docs/) |
||||
- Inisialisasi project `{name}` |
||||
``` |
||||
|
||||
### 5. `{path}/docs/changelog.md` |
||||
|
||||
Di `[Unreleased]` atau langsung versi: |
||||
|
||||
```markdown |
||||
## [{version}] - {YYYY-MM-DD} |
||||
|
||||
### Added |
||||
- Struktur dokumentasi standar AI-Agent-Standards |
||||
``` |
||||
|
||||
### 6. `{path}/docs/todo.md` |
||||
|
||||
- Masukkan `initial_todos` ke High/Medium/Low |
||||
- Seksi "Selesai (Sesi Ini)": bootstrap docs |
||||
|
||||
### 7. `{path}/docs/project-status.md` |
||||
|
||||
- Ringkasan = description |
||||
- Progress: Documentation = Done; implementasi sesuai status awal |
||||
- Next priority link ke todo.md |
||||
|
||||
### 8. `{path}/docs/issues.md` |
||||
|
||||
Biarkan struktur template (belum ada issue), ganti placeholder generik seminimal mungkin. |
||||
|
||||
### 9. `{path}/docs/server.md` (WAJIB) |
||||
|
||||
Salin dari `templates/repo/server.md`, lalu: |
||||
|
||||
- Isi **Project** path dan **Last updated** |
||||
- Jika INPUT punya `servers:`: isi tabel Host/Server, Aplikasi & Runtime, Database, Endpoint |
||||
- Isi **Mapping ke path project** dengan path monorepo project ini |
||||
- Jika server belum diketahui: biarkan tabel dengan satu baris placeholder dan catatan `TODO: isi saat infra diketahui` — **jangan hapus file** |
||||
- Credential location saja, **jangan** password/secret |
||||
|
||||
### 10. `{path}/docs/system-requirements.md` (WAJIB) |
||||
|
||||
- Isi tipe project, stack dari INPUT |
||||
- Tabel runtime/tool (JDK, Docker, Android Studio, SQL, dll.) — placeholder OK dengan TODO |
||||
- Seksi **Variabel URL & konfigurasi** — list variabel dari `.env.example` |
||||
- Cantumkan aturan no hardcode |
||||
|
||||
### 11. `{path}/.env.example` (WAJIB, root project) |
||||
|
||||
- Salin dari `templates/repo/.env.example` |
||||
- Sesuaikan nama variabel project (`API_BASE_URL`, dll.) |
||||
- Nilai = placeholder dev, **bukan** production secret |
||||
- Tambah komentar variabel khusus project (Android: `AGENT_API_BASE_URL`, dll.) |
||||
|
||||
### 12. `{path}/docs/guide/migration.md` (WAJIB) |
||||
|
||||
- Salin template; isi tabel inventori **jika** server/domain sudah diketahui |
||||
- Jika belum: biarkan checklist + catatan `TODO: isi saat migrasi pertama` |
||||
- Pastikan `guide/README.md` mengindeks migration.md |
||||
|
||||
--- |
||||
|
||||
## Update Workspace-Context.md (root monorepo) |
||||
|
||||
Untuk setiap project baru, **tambah baris** di tabel Project Aktif: |
||||
|
||||
| Repository | Path | Deskripsi | Status | Cold start | Context | |
||||
|------------|------|-----------|--------|------------|---------| |
||||
| `{name}` | `{path}/` | `{description}` | New | [`AGENTS.md`]({path}/AGENTS.md) | [`docs/context-index.md`]({path}/docs/context-index.md) | |
||||
|
||||
Tambah baris Quick Navigation: |
||||
|
||||
| Mulai kerja `{name}` | `{path}/AGENTS.md` -> `docs/ai-session-summary.md` | |
||||
|
||||
Jangan hapus project yang sudah ada. |
||||
|
||||
Jika ada seksi **Server Index** di `Workspace-Context.md`, tambah baris per host yang diketahui: |
||||
|
||||
| Host / IP | Project | Role | Runtime ringkas | Detail | |
||||
|-----------|---------|------|-----------------|--------| |
||||
| {ip} | `{path}` | {role} | {docker/nginx/SQL/...} | [server.md]({path}/docs/server.md) | |
||||
|
||||
Jika seksi belum ada, buat seksi `## Server Index (lintas project)` dengan tabel di atas (hanya indeks + link, detail di `docs/server.md`). |
||||
|
||||
**Jangan** overwrite `Workspace-Session.md` kecuali user minta (boleh sebut di laporan bahwa sesi berikutnya bisa menambahkan Active focus). |
||||
|
||||
--- |
||||
|
||||
## Aturan keamanan & kualitas |
||||
|
||||
- Encoding UTF-8 |
||||
- Tidak menulis secret/credential |
||||
- Tidak menghapus project/docs existing tanpa izin |
||||
- Jika `{path}` sudah punya `AGENTS.md` atau `docs/`: **stop dan tanya** overwrite / merge / skip |
||||
- Ikuti single owner: jangan menduplikasi backlog ke session summary |
||||
- Pengetahuan penting tidak boleh hanya di chat (sudah masuk docs lewat bootstrap ini) |
||||
|
||||
--- |
||||
|
||||
## Urutan eksekusi |
||||
|
||||
``` |
||||
1. Parse INPUT (semua project) |
||||
2. Baca template AI-Agent-Standards |
||||
3. Untuk tiap project: |
||||
a. Cek path belum ada konflik |
||||
b. Buat folder |
||||
c. Copy + isi file wajib |
||||
4. Update Workspace-Context.md |
||||
5. Final report |
||||
``` |
||||
|
||||
--- |
||||
|
||||
## Final Report (wajib ke user) |
||||
|
||||
Untuk setiap project: |
||||
|
||||
- Path dibuat |
||||
- File dibuat (daftar) |
||||
- has_api / has_guide |
||||
- server.md, system-requirements.md, .env.example, guide/migration.md |
||||
- Version awal |
||||
- Link cold start: `{path}/AGENTS.md` |
||||
|
||||
Workspace: |
||||
|
||||
- Baris yang ditambahkan ke `Workspace-Context.md` |
||||
|
||||
Langkah user berikutnya: |
||||
|
||||
``` |
||||
Buka {path}/AGENTS.md lalu docs/ai-session-summary.md untuk lanjut kerja. |
||||
Akhir sesi: ikuti AI-Agent-Standards/prompts/end-of-session-handover.md |
||||
``` |
||||
|
||||
--- |
||||
|
||||
## Contoh pemanggilan singkat (user) |
||||
|
||||
``` |
||||
Ikuti AI-Agent-Standards/prompts/bootstrap-new-project.md |
||||
|
||||
projects: |
||||
- path: lagercloud.com/billing |
||||
name: Billing |
||||
description: Service tagihan Training Center |
||||
stack: Python FastAPI |
||||
type: api |
||||
has_api: true |
||||
has_guide: false |
||||
- path: lagercloud.com/notify |
||||
name: Notify |
||||
description: Notifikasi WA/email |
||||
stack: Python |
||||
type: app |
||||
has_api: true |
||||
has_guide: true |
||||
- path: tools/report-cli |
||||
name: Report CLI |
||||
description: CLI laporan internal |
||||
stack: Node.js |
||||
type: app |
||||
``` |
||||
|
||||
Agent wajib membuat ketiga project sesuai template tanpa menunggu instruksi tambahan selain field yang benar-benar hilang. |
||||
@ -0,0 +1,154 @@
@@ -0,0 +1,154 @@
|
||||
# Prompt AI Agent - End of Session Project Knowledge Preservation |
||||
|
||||
> **Trigger:** akhir sesi / sebelum commit-push. Alias: `/handover` |
||||
> **Workspace:** monorepo (satu git root, banyak subproject) |
||||
|
||||
--- |
||||
|
||||
## Objective |
||||
|
||||
Pindahkan pengetahuan sesi ke docs agar agent berikutnya lanjut dengan **token minimal** (< 2000 token cold start). |
||||
|
||||
Chat **bukan** penyimpanan pengetahuan. Catatan penting, arsitektur, flow, keputusan teknis **wajib** masuk docs (owner yang benar). |
||||
|
||||
--- |
||||
|
||||
## Scope |
||||
|
||||
Identifikasi subproject yang berubah. Project tanpa perubahan: skip. |
||||
|
||||
--- |
||||
|
||||
## Tier Handover |
||||
|
||||
### Tier 1 - Minimal (WAJIB jika ada perubahan kode/config) |
||||
|
||||
1. **OVERWRITE** `docs/ai-session-summary.md` |
||||
- Max 80 baris / ~1500 token |
||||
- Wajib: yaml + **TL;DR** + **Lanjut dari sini** + **Jangan** |
||||
- Detail opsional (omit-if-N/A) |
||||
- **Satu-satunya rolling session memory** - jangan andalkan WORKLOG/development-log |
||||
|
||||
2. **UPDATE** `docs/todo.md` |
||||
- Seksi "Selesai (Sesi Ini)" di-overwrite (bukan menumpuk) |
||||
|
||||
3. **APPEND** `docs/changelog.md` (Keep a Changelog saja) |
||||
|
||||
4. **APPEND** `docs/version.md` (poin-poin versi) — **wajib** jika deploy / naik versi / install ke device atau server; format bullet seperti entri semver yang ada; jangan overwrite entri lama |
||||
|
||||
5. **UPDATE** `AGENTS.md` (root project) **hanya jika** aturan kritis / pointer berubah |
||||
|
||||
### Tier 2 - Jika relevan |
||||
|
||||
| Kondisi | Aksi | |
||||
|---------|------| |
||||
| Bug / limitation | `docs/issues.md` | |
||||
| Keputusan arsitektur / flow sistem | `docs/adr/` | |
||||
| Flow / prosedur step-by-step | `docs/guide/` | |
||||
| Host/IP, runtime (Docker/nginx/IIS/Apache), DB, port berubah | `docs/server.md` | |
||||
| System requirement (OS, JDK, Docker, DB versi) berubah | `docs/system-requirements.md` | |
||||
| Migrasi server/domain / cutover URL | `docs/guide/migration.md` + `.env.example` | |
||||
| Variabel env/URL baru | `.env.example` (root project); kode baca env — **no hardcode** | |
||||
| Progress area | `docs/project-status.md` | |
||||
| Dokumen/struktur baru | `docs/context-index.md` | |
||||
| API berubah | `docs/api/` | |
||||
|
||||
### Tier 3 - Monorepo |
||||
|
||||
**OVERWRITE** `Workspace-Session.md`: |
||||
- Seksi **Active focus** di atas (1-3 baris per project) |
||||
- Tabel project + link session summary + version |
||||
- Cross-project impact |
||||
- Jangan duplikasi isi session summary |
||||
|
||||
--- |
||||
|
||||
## Single Owner |
||||
|
||||
| Informasi | Owner | |
||||
|-----------|-------| |
||||
| Cold start / aturan kritis | `AGENTS.md` (root project) | |
||||
| Narasi sesi (rolling) | `docs/ai-session-summary.md` | |
||||
| Priority / TODO | `docs/todo.md` | |
||||
| Bug / RCA | `docs/issues.md` | |
||||
| Changelog kategori | `docs/changelog.md` | |
||||
| Poin versi | `docs/version.md` | |
||||
| API | `docs/api/` | |
||||
| Step-by-step / flow prosedur | `docs/guide/` | |
||||
| Server / IP / runtime / DB | `docs/server.md` | |
||||
| System requirements | `docs/system-requirements.md` | |
||||
| Migrasi server/domain | `docs/guide/migration.md` | |
||||
| Template URL/env (dynamic) | `.env.example` (root) | |
||||
| Peta domain | `docs/context-index.md` (on-demand) | |
||||
| Lintas project sesi | `Workspace-Session.md` | |
||||
|
||||
**Arsip (bukan jalur baca wajib):** WORKLOG, development-log, history panjang. |
||||
|
||||
--- |
||||
|
||||
## Read budget (untuk AI berikutnya) |
||||
|
||||
| Tujuan | Baca maksimal | |
||||
|--------|----------------| |
||||
| Lanjut task yang sama | `AGENTS.md` + `ai-session-summary` (TL;DR/Lanjut/Jangan) | |
||||
| Ambil task baru | + `todo.md` (High saja) | |
||||
| Debug | + `issues.md` (ID terkait) | |
||||
| Ubah API | + `docs/api/` | |
||||
| Ikuti prosedur | + `docs/guide/` | |
||||
| Deploy / debug koneksi / infra | + `docs/server.md` | |
||||
| Migrasi / ganti domain | + `docs/guide/migration.md` + `.env.example` | |
||||
| Setup tool chain | + `docs/system-requirements.md` | |
||||
| Keputusan arsitektur | + `docs/adr/` terkait | |
||||
| Navigasi domain | + `context-index.md` Zona B | |
||||
|
||||
**Urutan cold start:** |
||||
|
||||
``` |
||||
Workspace-Session.md (jika multi-project; baca Active focus dulu) |
||||
-> {project}/AGENTS.md |
||||
-> {project}/docs/ai-session-summary.md |
||||
-> STOP - mulai kerja |
||||
``` |
||||
|
||||
Target: **< 2000 token** sebelum coding. |
||||
|
||||
|
||||
--- |
||||
|
||||
## No hardcoded URL (wajib) |
||||
|
||||
- Semua **URL, domain, base path, host:port** di aplikasi harus dari **environment** atau config yang dibaca saat runtime/build (.env, env var, BuildConfig, gradle.properties). |
||||
- **Dilarang** hardcode di source code kecuali unit test mock atau .env.example placeholder. |
||||
- Saat migrasi domain/server: ubah .env / server config + update .env.example, server.md, guide/migration.md — **bukan** scatter edit URL di banyak file kode. |
||||
- Android/Kotlin: base URL lewat BuildConfig/flavor, bukan string literal di Activity/Service. |
||||
- Commit: .env.example boleh; .env dengan secret **tidak**. |
||||
|
||||
--- |
||||
|
||||
## Knowledge compression |
||||
|
||||
- Ringkas; omit-if-N/A; referensi jangan salin |
||||
- **Harus masuk docs:** solusi bug, troubleshooting, config, deploy, keputusan teknis, arsitektur, flow, **system requirements**, **inventori server**, **langkah migrasi server/domain**, root cause, workaround, dependency, versi |
||||
- **Jangan:** secret, log mentah, chat verbatim, info yang sudah di kode |
||||
|
||||
--- |
||||
|
||||
## Validation |
||||
|
||||
Lihat `templates/handover-checklist.md`. |
||||
|
||||
Minimal: |
||||
- [ ] Tier 1 lengkap |
||||
- [ ] Session summary punya TL;DR + Lanjut + Jangan, <= 80 baris |
||||
- [ ] Tidak ada pengetahuan penting hanya di chat |
||||
- [ ] Tidak ada secret di diff |
||||
|
||||
--- |
||||
|
||||
## Git |
||||
|
||||
Commit Conventional Commits hanya jika user meminta. Push hanya jika diminta. |
||||
|
||||
## Final Report |
||||
|
||||
Project, tier, file, version, TODO/issue/ADR baru, ringkasan, next steps. |
||||
@ -0,0 +1,63 @@
@@ -0,0 +1,63 @@
|
||||
# AI Agent Command - Generate AI Session Summary |
||||
|
||||
> **Trigger:** `/session-summary` |
||||
> **Target file:** `docs/ai-session-summary.md` |
||||
> **Strategi:** OVERWRITE (bukan append) |
||||
> **Batas keras:** max 80 baris / ~1500 token |
||||
> **Satu-satunya rolling session memory** per project |
||||
|
||||
--- |
||||
|
||||
## Tujuan |
||||
|
||||
Overwrite `docs/ai-session-summary.md` agar agent berikutnya lanjut kerja dari **TL;DR + Lanjut dari sini + Jangan** tanpa baca docs lain. |
||||
|
||||
Target cold-start total (AGENTS + session): **< 2000 token**. |
||||
|
||||
--- |
||||
|
||||
## Aturan tulis |
||||
|
||||
1. File selalu di-overwrite |
||||
2. **Wajib di atas:** yaml metadata + TL;DR + Lanjut dari sini + Jangan |
||||
3. Blok **Detail** hanya jika perlu; hapus jika TL;DR cukup |
||||
4. Omit seksi kosong - jangan isi N/A |
||||
5. Max 80 baris total |
||||
6. "Catatan untuk AI berikutnya" max 5 bullet |
||||
7. Jangan salin changelog / daftar file / backlog todo / RCA issues |
||||
8. Jangan mengandalkan WORKLOG atau development-log sebagai pengganti file ini |
||||
|
||||
--- |
||||
|
||||
## Struktur wajib |
||||
|
||||
```yaml |
||||
session: ... |
||||
project: ... |
||||
version: ... |
||||
status: ready|blocked|in-progress |
||||
next: ... |
||||
``` |
||||
|
||||
## TL;DR |
||||
- max 5 bullet |
||||
|
||||
## Lanjut dari sini |
||||
1. ... |
||||
2. ... |
||||
|
||||
## Jangan |
||||
- max 5 bullet |
||||
|
||||
## Detail (opsional) |
||||
- Perubahan material, feature, bug, config/api/db, catatan |
||||
|
||||
Template: `templates/repo/ai-session-summary.md` |
||||
|
||||
--- |
||||
|
||||
## Setelah selesai |
||||
|
||||
1. Tier 1 lain: todo.md, changelog.md, version.md |
||||
2. AGENTS.md hanya jika aturan kritis berubah |
||||
3. Multi-project: Workspace-Session.md (sertakan Active focus) |
||||
@ -0,0 +1,50 @@
@@ -0,0 +1,50 @@
|
||||
# Rekomendasi Standar Dokumentasi AI |
||||
|
||||
Status: **diadopsi ke template** (termasuk optimasi token 2026-07-04). |
||||
|
||||
--- |
||||
|
||||
## Diadopsi |
||||
|
||||
1. Session ID + yaml metadata di session summary |
||||
2. STRATEGY badge |
||||
3. Tier handover (Minimal / Relevan / Monorepo) |
||||
4. Single owner |
||||
5. Keep a Changelog saja |
||||
6. omit-if-N/A |
||||
7. todo "Selesai sesi ini" overwrite |
||||
8. context-index boleh tebal, berlapis (Zona A / Zona B) |
||||
9. Monorepo model |
||||
10. docs/api/ dan docs/guide/ |
||||
11. docs/version.md — **wajib append** setiap deploy / naik versi (poin-poin perubahan) |
||||
12. Pengetahuan penting tidak boleh hanya di chat |
||||
13. **AGENTS.md cold start** (root project, max ~40 baris) |
||||
14. **Session summary:** TL;DR + Lanjut + Jangan; max 80 baris |
||||
15. **Satu rolling memory:** hanya ai-session-summary; WORKLOG/development-log = arsip |
||||
16. **Read budget** + urutan stop-early (< 2000 token) |
||||
17. **Workspace-Session Active focus** |
||||
18. **docs/server.md** - inventori host/IP, runtime, port |
||||
19. **docs/system-requirements.md** - OS, runtime, tool minimum |
||||
20. **.env.example** - template URL/env (dynamic, no hardcode) |
||||
21. **docs/guide/migration.md** - migrasi server/domain + checklist cutover |
||||
|
||||
--- |
||||
|
||||
## Opsional (belum diwajibkan) |
||||
|
||||
- `docs/.handover-meta.json` untuk CI |
||||
- Pre-commit hook otomatis: kode berubah => session summary + version harus berubah |
||||
- Wiring slash commands per agent tool |
||||
|
||||
--- |
||||
|
||||
## Estimasi token cold start |
||||
|
||||
| Skenario | File | Estimasi | |
||||
|----------|------|----------| |
||||
| Lanjut task (satu project) | AGENTS + session (TL;DR) | **~700-2000** | |
||||
| Multi-project | Workspace-Session Active focus + AGENTS + session | ~1000-2500 | |
||||
| Ambil task baru | + todo High | +200-500 | |
||||
| Debug | + issues ID | +300-800 | |
||||
|
||||
Target: **< 2000 token** sebelum coding pada jalur panas. |
||||
@ -0,0 +1,53 @@
@@ -0,0 +1,53 @@
|
||||
# Handover Checklist |
||||
|
||||
<!-- Gunakan sebelum commit/push. Ikuti TIER. --> |
||||
|
||||
## Tier 1 - Minimal |
||||
|
||||
Per project yang berubah: |
||||
|
||||
- [ ] `docs/ai-session-summary.md` di-**overwrite** |
||||
- [ ] yaml metadata ada |
||||
- [ ] **TL;DR** (max 5 bullet) |
||||
- [ ] **Lanjut dari sini** (1-3 item) |
||||
- [ ] **Jangan** (max 5 bullet) |
||||
- [ ] Total <= 80 baris; Detail di-omit jika tidak perlu |
||||
- [ ] `docs/todo.md` diupdate; "Selesai (Sesi Ini)" di-overwrite |
||||
- [ ] `docs/changelog.md` di-append (Keep a Changelog) |
||||
- [ ] `docs/version.md` di-append (poin-poin) — **wajib** jika deploy / naik versi / install ke device-server |
||||
- [ ] Versi build config di-bump (gradle, package.json, dll.) selaras entri `version.md` |
||||
- [ ] `AGENTS.md` diupdate **hanya jika** aturan kritis berubah |
||||
|
||||
## Tier 2 - Jika relevan |
||||
|
||||
- [ ] `docs/issues.md` |
||||
- [ ] `docs/adr/` (arsitektur / flow sistem) |
||||
- [ ] `docs/guide/` (prosedur step-by-step) |
||||
- [ ] `docs/project-status.md` |
||||
- [ ] `docs/context-index.md` |
||||
- [ ] `docs/api/` |
||||
- [ ] `docs/server.md` (host/IP, runtime, DB berubah) |
||||
- [ ] `docs/system-requirements.md` (OS/runtime/tool berubah) |
||||
- [ ] `.env.example` + kode **no hardcoded URL** (domain/server migrasi) |
||||
- [ ] `docs/guide/migration.md` (jika migrasi/cutover) |
||||
|
||||
## Tier 3 - Monorepo |
||||
|
||||
- [ ] `Workspace-Session.md` di-overwrite |
||||
- [ ] Seksi **Active focus** diisi |
||||
- [ ] Link session summary + version per project |
||||
- [ ] Cross-project impact |
||||
|
||||
## Quality |
||||
|
||||
- [ ] Rolling memory hanya di ai-session-summary (bukan WORKLOG sebagai pengganti) |
||||
- [ ] Tidak ada pengetahuan penting hanya di chat |
||||
- [ ] Tidak ada duplikasi owner (todo/issues/session) |
||||
- [ ] Tidak ada secret / log mentah panjang |
||||
- [ ] Agent berikutnya bisa stop setelah AGENTS + session summary |
||||
|
||||
## Git |
||||
|
||||
- [ ] Review perubahan |
||||
- [ ] Conventional Commit (jika diminta) |
||||
- [ ] Final report ke user |
||||
@ -0,0 +1,41 @@
@@ -0,0 +1,41 @@
|
||||
# .env.example — Template konfigurasi (AMAN di-commit) |
||||
# Copy ke .env di root project yang sama (JANGAN commit .env) |
||||
# Semua URL/host/domain aplikasi HARUS dibaca dari variabel ini (no hardcode di kode) |
||||
|
||||
# --- Environment --- |
||||
APP_ENV=development |
||||
# development | staging | production |
||||
|
||||
# --- Public URLs (ubah saat migrasi domain) --- |
||||
APP_URL=https://app-dev.example.com |
||||
API_BASE_URL=https://api-dev.example.com |
||||
# API_BASE_URL=http://10.0.0.1:8055 |
||||
|
||||
# --- Auth / SSO (jika ada) --- |
||||
# AUTH_ISSUER_URL= |
||||
# OIDC_REDIRECT_URI= |
||||
|
||||
# --- Database (host saja di docs; credential di .env lokal) --- |
||||
DB_HOST=127.0.0.1 |
||||
DB_PORT=5432 |
||||
DB_NAME=myapp |
||||
DB_USER= |
||||
DB_PASSWORD= |
||||
|
||||
# --- Redis / cache (opsional) --- |
||||
# REDIS_URL=redis://127.0.0.1:6379/0 |
||||
|
||||
# --- Internal service (monorepo) --- |
||||
# LDAP_API_URL= |
||||
# AGENT_API_URL= |
||||
|
||||
# --- Android / build-time (alternatif jika tidak pakai .env runtime) --- |
||||
# AGENT_API_BASE_URL=https://agent-dev.example.com |
||||
|
||||
# --- Logging / debug --- |
||||
# LOG_LEVEL=info |
||||
# DEBUG=false |
||||
|
||||
# Dokumentasi variabel: docs/system-requirements.md |
||||
# Migrasi server/domain: docs/guide/migration.md |
||||
# Inventori host: docs/server.md |
||||
@ -0,0 +1,60 @@
@@ -0,0 +1,60 @@
|
||||
# AGENTS.md - Cold Start |
||||
|
||||
<!-- STRATEGY: UPDATE JARANG | Baca PERTAMA saat buka project. Max ~40 baris. --> |
||||
<!-- Lokasi: root project (sibling docs/), BUKAN di dalam docs/ --> |
||||
|
||||
> Project: `{path/relatif/dari/root monorepo}` |
||||
> Sesi terakhir: [docs/ai-session-summary.md](./docs/ai-session-summary.md) |
||||
> Peta lengkap (on-demand): [docs/context-index.md](./docs/context-index.md) |
||||
> Env template: [.env.example](./.env.example) |
||||
|
||||
## Apa ini? |
||||
|
||||
{1-2 kalimat: apa project ini dan perannya di monorepo} |
||||
|
||||
## Aturan kritis |
||||
|
||||
- {aturan 1 - mis. tidak akses DB langsung} |
||||
- **No hardcoded URL/domain/IP** — baca dari `.env` / env var / BuildConfig / config |
||||
- Copy `.env.example` -> `.env` lokal; jangan commit `.env` berisi secret |
||||
- No commit kecuali user minta eksplisit |
||||
- **Deploy / rilis:** naikkan versi di build config + **wajib append** [docs/version.md](./docs/version.md) (poin-poin perubahan) |
||||
- {aturan lain - max 7 bullet total} |
||||
|
||||
## Lanjut kerja (urutan baca) |
||||
|
||||
``` |
||||
1. AGENTS.md <- Anda di sini (~200-400 token) |
||||
2. docs/ai-session-summary.md <- TL;DR + Lanjut + Jangan |
||||
3. STOP - mulai kerja |
||||
4. On-demand: |
||||
- docs/todo.md |
||||
- docs/issues.md |
||||
- docs/api/ |
||||
- docs/guide/migration.md (pindah server/domain) |
||||
- docs/system-requirements.md |
||||
- docs/server.md |
||||
- .env.example |
||||
- docs/context-index.md |
||||
``` |
||||
|
||||
**Jangan cold start:** changelog penuh, WORKLOG, development-log. |
||||
|
||||
**Rolling session memory = hanya** `docs/ai-session-summary.md`. |
||||
|
||||
## Pointer cepat |
||||
|
||||
| Butuh | Buka | |
||||
|-------|------| |
||||
| Priority | [docs/todo.md](./docs/todo.md) | |
||||
| Versi / deploy | [docs/version.md](./docs/version.md) | |
||||
| Bug / RCA | [docs/issues.md](./docs/issues.md) | |
||||
| API | [docs/api/](./docs/api/) | |
||||
| Migrasi server/domain | [docs/guide/migration.md](./docs/guide/migration.md) | |
||||
| System requirements | [docs/system-requirements.md](./docs/system-requirements.md) | |
||||
| Server / infra | [docs/server.md](./docs/server.md) | |
||||
| Variabel URL/env | [.env.example](./.env.example) | |
||||
|
||||
## Multi-project |
||||
|
||||
`Workspace-Session.md` -> `AGENTS.md` project terkait. |
||||
@ -0,0 +1,50 @@
@@ -0,0 +1,50 @@
|
||||
# ADR-{NNN}: {Judul Keputusan} |
||||
|
||||
<!-- STRATEGY: APPEND | Satu file per keputusan arsitektur --> |
||||
|
||||
**Owner:** keputusan arsitektur (context, decision, alternatives, consequences). |
||||
Simpan di `docs/adr/NNN-judul-singkat.md`. |
||||
|
||||
| Field | Value | |
||||
|-------|-------| |
||||
| Status | Proposed / Accepted / Deprecated / Superseded | |
||||
| Date | {YYYY-MM-DD} | |
||||
| Author | {AI Agent / Developer} | |
||||
| Session | {session-id} | |
||||
| Version | {x.y.z jika terkait rilis} | |
||||
|
||||
--- |
||||
|
||||
## Context |
||||
|
||||
{Masalah atau situasi yang memerlukan keputusan} |
||||
|
||||
--- |
||||
|
||||
## Decision |
||||
|
||||
{Keputusan yang diambil} |
||||
|
||||
--- |
||||
|
||||
## Alternatives Considered |
||||
|
||||
| Alternatif | Pro | Con | |
||||
|------------|-----|-----| |
||||
| | | | |
||||
|
||||
--- |
||||
|
||||
## Consequences |
||||
|
||||
**Positif:** |
||||
- |
||||
|
||||
**Negatif / Trade-off:** |
||||
- |
||||
|
||||
--- |
||||
|
||||
## References |
||||
|
||||
- {link ke issue, PR, docs terkait} |
||||
@ -0,0 +1,78 @@
@@ -0,0 +1,78 @@
|
||||
# AI Session Summary |
||||
|
||||
<!-- STRATEGY: OVERWRITE | Satu-satunya rolling session memory per project --> |
||||
<!-- BATAS KERAS: max 80 baris / ~1500 token. Omit seksi N/A. --> |
||||
<!-- READ: setelah AGENTS.md. Cukup TL;DR + Lanjut + Jangan untuk lanjut kerja. --> |
||||
|
||||
**Jangan duplikasi:** changelog/version (daftar file), todo (backlog), issues (RCA penuh), project-status. |
||||
|
||||
File kronologis lain (WORKLOG, development-log) **bukan** pengganti file ini dan **bukan** jalur baca wajib. |
||||
|
||||
--- |
||||
|
||||
```yaml |
||||
session: {YYYY-MM-DD-judul-singkat} |
||||
project: {path/relatif} |
||||
version: {x.y.z} |
||||
status: ready|blocked|in-progress |
||||
next: {satu baris prioritas langsung} |
||||
previous: {session-id sebelumnya atau N/A} |
||||
agent: {Cursor/Cline/dll} |
||||
branch: {branch} |
||||
``` |
||||
|
||||
--- |
||||
|
||||
## TL;DR |
||||
|
||||
- {max 5 bullet - apa yang dikerjakan dan hasilnya} |
||||
- |
||||
|
||||
--- |
||||
|
||||
## Lanjut dari sini |
||||
|
||||
1. {prioritas langsung sesi berikutnya} |
||||
2. {opsional} |
||||
3. {opsional} |
||||
|
||||
> Backlog penuh: [todo.md](./todo.md) |
||||
|
||||
--- |
||||
|
||||
## Jangan |
||||
|
||||
- {pitfall / regresi / hal yang tidak boleh diulang - max 5 bullet} |
||||
- |
||||
|
||||
--- |
||||
|
||||
## Detail (hanya jika perlu) |
||||
|
||||
<!-- Hapus seluruh blok Detail jika TL;DR sudah cukup. Max sisa file agar total <= 80 baris. --> |
||||
|
||||
### Perubahan material |
||||
|
||||
> [changelog.md](./changelog.md) | [version.md](./version.md) |
||||
|
||||
- {1-5 bullet dampak - bukan path file} |
||||
|
||||
### Feature |
||||
|
||||
- {fitur} |
||||
|
||||
### Bug fix |
||||
|
||||
| Bug | Root cause | Fix | Ref | |
||||
|-----|------------|-----|-----| |
||||
| | | | [ISS-NNN](./issues.md) | |
||||
|
||||
### Config / infra / API / DB |
||||
|
||||
- {ringkas; API detail di [api/](./api/); server/IP/runtime di [server.md](./server.md)} |
||||
|
||||
### Catatan untuk AI berikutnya |
||||
|
||||
- {hanya info yang tidak ada di docs lain - max 5 bullet} |
||||
|
||||
**On-demand:** [context-index.md](./context-index.md) | [todo.md](./todo.md) | [issues.md](./issues.md) |
||||
@ -0,0 +1,44 @@
@@ -0,0 +1,44 @@
|
||||
# API Documentation |
||||
|
||||
<!-- STRATEGY: UPDATE | Wajib jika project menerapkan API atau framework API --> |
||||
|
||||
**Owner:** kontrak API (endpoint, auth, request/response, error code). |
||||
Session summary hanya ringkas perubahan — detail tetap di sini. |
||||
|
||||
## Indeks Endpoint |
||||
|
||||
| Method | Path | Deskripsi | Auth | Doc | |
||||
|--------|------|-----------|------|-----| |
||||
| | | | | [nama.md](./nama.md) | |
||||
|
||||
## Konvensi |
||||
|
||||
- Satu file per resource/domain, atau satu file OpenAPI jika lebih cocok. |
||||
- Breaking change wajib dicatat di [../changelog.md](../changelog.md) dan [../version.md](../version.md). |
||||
- Contoh request/response tanpa credential nyata. |
||||
|
||||
## Template Endpoint |
||||
|
||||
### `{METHOD} {/path}` |
||||
|
||||
**Deskripsi:** {apa yang dilakukan} |
||||
|
||||
**Auth:** {none / bearer / api-key / session} |
||||
|
||||
**Request:** |
||||
|
||||
```json |
||||
{} |
||||
``` |
||||
|
||||
**Response 200:** |
||||
|
||||
```json |
||||
{} |
||||
``` |
||||
|
||||
**Error:** |
||||
|
||||
| Code | Meaning | |
||||
|------|---------| |
||||
| | | |
||||
@ -0,0 +1,46 @@
@@ -0,0 +1,46 @@
|
||||
# Changelog |
||||
|
||||
<!-- STRATEGY: APPEND | Riwayat permanen — jangan overwrite --> |
||||
|
||||
Format: [Keep a Changelog](https://keepachangelog.com/). |
||||
Satu format saja — jangan campur entri per-sesi terpisah. |
||||
|
||||
**Owner:** riwayat perubahan permanen per kategori (Added / Changed / Fixed / Removed / Deprecated / Security). |
||||
Session summary **tidak** mengulang daftar file atau entri changelog — cukup link ke sini. |
||||
|
||||
Versi rilis berpoin: lihat [version.md](./version.md). |
||||
|
||||
--- |
||||
|
||||
## [Unreleased] |
||||
|
||||
### Added |
||||
- |
||||
|
||||
### Changed |
||||
- |
||||
|
||||
### Fixed |
||||
- |
||||
|
||||
### Removed |
||||
- |
||||
|
||||
### Deprecated |
||||
- |
||||
|
||||
### Security |
||||
- |
||||
|
||||
--- |
||||
|
||||
## [x.y.z] - {YYYY-MM-DD} |
||||
|
||||
### Added |
||||
- {fitur baru} |
||||
|
||||
### Fixed |
||||
- {bug fix} |
||||
|
||||
### Changed |
||||
- {perubahan perilaku} |
||||
@ -0,0 +1,141 @@
@@ -0,0 +1,141 @@
|
||||
# Context Index |
||||
|
||||
<!-- STRATEGY: UPDATE | Peta navigasi domain - boleh tebal, berlapis --> |
||||
<!-- READ: on-demand. Cold start = ../AGENTS.md dulu, lalu ai-session-summary.md --> |
||||
|
||||
> Multi-project: `Workspace-Session.md` (root) -> `{project}/AGENTS.md` -> `docs/ai-session-summary.md` -> **STOP**. |
||||
> File ini hanya jika perlu navigasi domain. |
||||
|
||||
Boleh tebal (spec, architecture, parent/sibling, checklist) seperti pola Kotlin. |
||||
Tetap **indeks + link**, bukan salinan isi dokumen lain. |
||||
|
||||
--- |
||||
|
||||
## Zona A - Always-read pointers |
||||
|
||||
| Item | Value | |
||||
|------|-------| |
||||
| Nama | {REPO_NAME} | |
||||
| Path monorepo | `{path/relatif/dari/root}` | |
||||
| Cold start | [../AGENTS.md](../AGENTS.md) | |
||||
| Sesi terakhir | [ai-session-summary.md](./ai-session-summary.md) | |
||||
| Priority aktif | [todo.md](./todo.md) | |
||||
| Server / infra | [server.md](./server.md) | |
||||
| System requirements | [system-requirements.md](./system-requirements.md) | |
||||
| Env / URL template | [../.env.example](../.env.example) | |
||||
| Versi | {x.y.z} - [version.md](./version.md) | |
||||
| Stack | {TECH_STACK} | |
||||
| Tipe | {app / api / library / infra / docs-only} | |
||||
| Last updated | {YYYY-MM-DD} | |
||||
|
||||
**Rolling session memory:** hanya [ai-session-summary.md](./ai-session-summary.md). |
||||
Arsip (jangan cold-start): WORKLOG, development-log, changelog penuh, version history penuh. |
||||
|
||||
--- |
||||
|
||||
## Zona B - On-demand map |
||||
|
||||
> Baca baris di bawah **hanya jika tugas menyentuh area tersebut**. |
||||
|
||||
### Dokumentasi inti |
||||
|
||||
| Dokumen | Isi | Kapan baca | |
||||
|---------|-----|------------| |
||||
| [ai-session-summary.md](./ai-session-summary.md) | Narasi sesi (overwrite) | Setelah AGENTS | |
||||
| [todo.md](./todo.md) | Priority aktif | Ambil / ubah task | |
||||
| [project-status.md](./project-status.md) | Progress area | Butuh status luas | |
||||
| [issues.md](./issues.md) | Bug / RCA | Debug | |
||||
| [changelog.md](./changelog.md) | Keep a Changelog | Audit riwayat | |
||||
| [version.md](./version.md) | Poin per versi | Cek versi / rilis | |
||||
| [server.md](./server.md) | Host/IP, runtime, DB, port | Deploy / debug koneksi / ubah infra | |
||||
| [system-requirements.md](./system-requirements.md) | OS, runtime, tool minimum | Setup / upgrade / migrasi | |
||||
| [guide/migration.md](./guide/migration.md) | Migrasi server/domain | Cutover URL/env | |
||||
| [../.env.example](../.env.example) | Variabel URL/host (template) | Konfigurasi dynamic URL | |
||||
| [adr/](./adr/) | Keputusan arsitektur | Ubah arsitektur | |
||||
|
||||
### API dan guide (jika berlaku) |
||||
|
||||
| Kondisi | Path | Kapan baca | |
||||
|---------|------|------------| |
||||
| Project API / framework API | [api/](./api/) | Ubah / konsumsi endpoint | |
||||
| Prosedur step-by-step | [guide/](./guide/) | Ikuti runbook / setup | |
||||
|
||||
### Spesifikasi / architecture |
||||
|
||||
| Dokumen | Path | Kapan baca | |
||||
|---------|------|------------| |
||||
| | | | |
||||
|
||||
### Environment / development |
||||
|
||||
| Dokumen | Path | Kapan baca | |
||||
|---------|------|------------| |
||||
| | | | |
||||
|
||||
### Parent / sibling (monorepo) |
||||
|
||||
| Dokumen | Path | Kapan baca | |
||||
|---------|------|------------| |
||||
| | | | |
||||
|
||||
--- |
||||
|
||||
## Struktur kode |
||||
|
||||
``` |
||||
{root-project}/ |
||||
├── AGENTS.md # cold start (wajib) |
||||
├── .env.example # template URL/env (commit OK) |
||||
├── docs/ # dokumentasi standar |
||||
└── {modul}/ # {deskripsi} |
||||
``` |
||||
|
||||
--- |
||||
|
||||
## Dependency |
||||
|
||||
| Project / Service | Relasi | |
||||
|-------------------|--------| |
||||
| | | |
||||
|
||||
--- |
||||
|
||||
## Environment |
||||
|
||||
> Detail inventori server: **[server.md](./server.md)** (single owner). |
||||
|
||||
| Env | URL / Host | Catatan | |
||||
|-----|------------|---------| |
||||
| dev | | ringkas; detail di server.md | |
||||
|
||||
Credential: {lokasi vault/env} - jangan simpan secret di docs. |
||||
|
||||
--- |
||||
|
||||
## Aturan kritis AI |
||||
|
||||
> Duplikat singkat dari AGENTS.md - detail aturan di AGENTS.md. |
||||
|
||||
- Minimal diff - fokus scope project ini. |
||||
- No commit kecuali user minta. |
||||
- Single owner: priority -> todo; bug -> issues; sesi -> ai-session-summary. |
||||
- Perubahan material -> version.md + changelog.md. |
||||
- Host/IP/runtime/DB berubah -> update server.md. |
||||
- Tool/OS requirement berubah -> update system-requirements.md. |
||||
- Migrasi server/domain -> update guide/migration.md, .env.example, server.md; **no hardcoded URL** di kode. |
||||
- Pengetahuan penting tidak boleh hanya di chat. |
||||
- Implementasi tanpa Tier 1 handover = belum selesai. |
||||
|
||||
--- |
||||
|
||||
## Checklist |
||||
|
||||
### Sebelum implementasi |
||||
- [ ] Baca AGENTS.md + ai-session-summary (TL;DR / Lanjut / Jangan) |
||||
- [ ] todo / issues hanya jika perlu |
||||
|
||||
### Setelah implementasi (Tier 1) |
||||
- [ ] Overwrite ai-session-summary (max 80 baris; TL;DR wajib) |
||||
- [ ] Update todo.md |
||||
- [ ] Append changelog.md + version.md |
||||
- [ ] Update AGENTS.md hanya jika aturan kritis berubah |
||||
@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
|
||||
# Guides |
||||
|
||||
<!-- STRATEGY: UPDATE | Wajib jika project punya prosedur step-by-step khusus --> |
||||
|
||||
**Owner:** panduan operasional berurutan (setup, deploy, runbook, migrasi, troubleshooting alur). |
||||
|
||||
## Indeks Guide |
||||
|
||||
| Guide | Path | Kapan dipakai | |
||||
|-------|------|---------------| |
||||
| Migrasi server/domain | [migration.md](./migration.md) | Pindah server, ganti IP/domain, cutover env | |
||||
| | [nama.md](./nama.md) | | |
||||
|
||||
**Wajib ada:** [migration.md](./migration.md) untuk semua project (isi saat migrasi atau placeholder checklist). |
||||
|
||||
## Template Guide tambahan |
||||
|
||||
# {Judul Guide} |
||||
|
||||
## Prasyarat |
||||
- {prasyarat} |
||||
|
||||
## Langkah |
||||
1. {langkah 1} |
||||
|
||||
## Verifikasi |
||||
- {cara memastikan berhasil} |
||||
|
||||
## Rollback |
||||
- {jika gagal} |
||||
@ -0,0 +1,120 @@
@@ -0,0 +1,120 @@
|
||||
# Migration Guide — Server & Domain |
||||
|
||||
<!-- STRATEGY: UPDATE | Owner prosedur migrasi infra/domain project ini --> |
||||
<!-- READ: saat pindah server, ganti IP, ganti domain, atau cutover env --> |
||||
|
||||
**Owner:** checklist migrasi server/domain, urutan cutover, verifikasi, rollback. |
||||
Inventori host: [../server.md](../server.md). Requirement tool: [../system-requirements.md](../system-requirements.md). |
||||
Template env: `../../.env.example` (root project). |
||||
|
||||
**Prinsip:** URL/domain **dynamic** — ubah `.env` / config, bukan source code (kecuali refactor env var baru). |
||||
|
||||
--- |
||||
|
||||
## Kapan pakai guide ini |
||||
|
||||
- Migrasi app/service ke server baru (IP/host berubah) |
||||
- Ganti domain (mis. `old.example.com` -> `new.example.com`) |
||||
- Pindah database ke host/instance baru |
||||
- Cutover staging -> prod dengan URL baru |
||||
|
||||
--- |
||||
|
||||
## Inventori sebelum migrasi |
||||
|
||||
| Item | Nilai saat ini | Nilai target | File yang harus diupdate | |
||||
|------|----------------|--------------|--------------------------| |
||||
| Domain / base URL | | | `.env.example`, `.env` (lokal), [server.md](../server.md) | |
||||
| API base URL | | | kode baca env saja | |
||||
| DB host | | | `.env.example`, server.md | |
||||
| Reverse proxy | | | nginx/IIS config path di repo | |
||||
| SSL / cert | | | | |
||||
| DNS record | | | catatan di server.md | |
||||
|
||||
--- |
||||
|
||||
## Variabel env yang terpengaruh |
||||
|
||||
Salin dari `.env.example`, isi kolom old/new: |
||||
|
||||
| Variabel | Old | New | Sudah di `.env` prod? | |
||||
|----------|-----|-----|------------------------| |
||||
| `API_BASE_URL` | | | | |
||||
| `APP_URL` | | | | |
||||
| `DB_HOST` | | | | |
||||
| `{CUSTOM}` | | | | |
||||
|
||||
Commit yang boleh: `.env.example`, docs — **jangan** commit `.env` berisi secret. |
||||
|
||||
--- |
||||
|
||||
## Langkah migrasi (server) |
||||
|
||||
1. **Persiapan** |
||||
- [ ] Backup data & config server lama |
||||
- [ ] Server baru memenuhi [system-requirements.md](../system-requirements.md) |
||||
- [ ] Install runtime/stack (Docker, nginx, DB, dll.) di server baru |
||||
- [ ] Siapkan `.env` di server baru dari `.env.example` |
||||
|
||||
2. **Deploy ke server baru (parallel)** |
||||
- [ ] Deploy kode/config ke server baru |
||||
- [ ] Point `.env` ke dependency internal (DB, Redis, dll.) |
||||
- [ ] Smoke test internal (IP/host langsung, belum DNS publik) |
||||
|
||||
3. **Cutover** |
||||
- [ ] Update DNS / firewall / load balancer |
||||
- [ ] Update reverse proxy (nginx/IIS) ke backend baru |
||||
- [ ] Update `.env` production dengan URL/host final |
||||
- [ ] Restart service / container |
||||
|
||||
4. **Verifikasi** |
||||
- [ ] Health check endpoint |
||||
- [ ] Login / auth flow |
||||
- [ ] Integrasi ke project monorepo lain (jika ada) |
||||
- [ ] Client app (APK/web) masih pakai env — rebuild hanya jika BuildConfig berubah |
||||
|
||||
5. **Dokumentasi (wajib)** |
||||
- [ ] Update [../server.md](../server.md) (host, URL, mapping path) |
||||
- [ ] Update `.env.example` jika nama variabel/placeholder berubah |
||||
- [ ] Append entri migrasi di [../version.md](../version.md) + [../changelog.md](../changelog.md) |
||||
- [ ] Overwrite [../ai-session-summary.md](../ai-session-summary.md) (Tier 1 handover) |
||||
|
||||
--- |
||||
|
||||
## Langkah migrasi (domain saja, server sama) |
||||
|
||||
1. [ ] Tambah DNS / cert untuk domain baru |
||||
2. [ ] Update reverse proxy `server_name` / binding |
||||
3. [ ] Ubah `.env`: `API_BASE_URL`, `APP_URL`, `CORS_ORIGIN`, dll. |
||||
4. [ ] Redirect domain lama -> baru (opsional, periode transisi) |
||||
5. [ ] Update docs: server.md, .env.example |
||||
6. [ ] Smoke test dari client dengan URL baru |
||||
|
||||
**Tidak perlu** ubah kode jika semua URL sudah dari env. |
||||
|
||||
--- |
||||
|
||||
## Android / mobile (Kotlin Agent dll.) |
||||
|
||||
| Area | Saat migrasi domain | |
||||
|------|---------------------| |
||||
| Base URL API | `gradle.properties` / `BuildConfig` / flavor — bukan hardcode di `.kt` | |
||||
| Network security | `network_security_config.xml` jika domain/cert berubah | |
||||
| Release | Rebuild APK jika BuildConfig berubah; OTA channel sesuai [release guide] | |
||||
|
||||
--- |
||||
|
||||
## Rollback |
||||
|
||||
1. Kembalikan DNS / proxy ke server/domain lama |
||||
2. Restore `.env` backup |
||||
3. Restart service |
||||
4. Catat rollback di [../issues.md](../issues.md) + session summary |
||||
|
||||
--- |
||||
|
||||
## Riwayat migrasi |
||||
|
||||
| Tanggal | Dari | Ke | Session / versi | Catatan | |
||||
|---------|------|-----|-----------------|---------| |
||||
| {YYYY-MM-DD} | {old host/domain} | {new} | {session-id} | | |
||||
@ -0,0 +1,52 @@
@@ -0,0 +1,52 @@
|
||||
# Issues |
||||
|
||||
<!-- STRATEGY: APPEND | Tandai resolved, jangan hapus history --> |
||||
|
||||
**Owner:** detail bug, root cause, workaround, limitation (single source). |
||||
Session summary dan project-status hanya merujuk ID issue — jangan salin RCA penuh. |
||||
|
||||
--- |
||||
|
||||
## Open Issues |
||||
|
||||
### ISS-{NNN}: {Judul} |
||||
|
||||
| Field | Value | |
||||
|-------|-------| |
||||
| Status | Open | |
||||
| Severity | Critical/High/Medium/Low | |
||||
| Found | {YYYY-MM-DD} | |
||||
| Session | {session-id} | |
||||
|
||||
**Deskripsi:** |
||||
{deskripsi singkat} |
||||
|
||||
**Root Cause:** |
||||
{root cause jika diketahui} |
||||
|
||||
**Workaround:** |
||||
{workaround jika ada} |
||||
|
||||
**Files terkait:** |
||||
- `path/to/file` |
||||
|
||||
--- |
||||
|
||||
## Resolved Issues |
||||
|
||||
### ISS-{NNN}: {Judul} |
||||
|
||||
| Field | Value | |
||||
|-------|-------| |
||||
| Status | Resolved | |
||||
| Resolved | {YYYY-MM-DD} | |
||||
| Fix | {ringkasan fix} | |
||||
| Version | {x.y.z — lihat version.md} | |
||||
|
||||
--- |
||||
|
||||
## Known Limitations |
||||
|
||||
| ID | Limitation | Reason | Ref | |
||||
|----|------------|--------|-----| |
||||
| LIM-001 | | | | |
||||
@ -0,0 +1,71 @@
@@ -0,0 +1,71 @@
|
||||
# Project Status |
||||
|
||||
<!-- STRATEGY: UPDATE | Status berkelanjutan proyek --> |
||||
|
||||
> Last updated: {YYYY-MM-DD} |
||||
> Session: [ai-session-summary.md](./ai-session-summary.md) |
||||
|
||||
**Owner:** ringkasan progress area (Done / In Progress / Blocked / Planned), blocker, technical debt ringkas. |
||||
**Bukan owner:** daftar TODO (lihat todo.md), detail bug (lihat issues.md), narasi sesi (lihat session summary). |
||||
|
||||
--- |
||||
|
||||
## Ringkasan |
||||
|
||||
{1-2 kalimat status proyek saat ini} |
||||
|
||||
--- |
||||
|
||||
## Progress |
||||
|
||||
| Area | Status | Catatan | |
||||
|------|--------|---------| |
||||
| {area} | {Done/In Progress/Blocked/Planned} | | |
||||
|
||||
--- |
||||
|
||||
## Fitur Selesai |
||||
|
||||
- [x] {fitur} |
||||
|
||||
--- |
||||
|
||||
## Fitur Sedang Dikerjakan |
||||
|
||||
- [ ] {fitur} - {progress%} - {catatan} |
||||
|
||||
--- |
||||
|
||||
## Technical Debt (ringkas) |
||||
|
||||
> Item actionable: [todo.md](./todo.md#technical-debt) |
||||
|
||||
| Item | Prioritas | |
||||
|------|-----------| |
||||
| | High/Medium/Low | |
||||
|
||||
--- |
||||
|
||||
## Known Issues (indeks) |
||||
|
||||
> Detail: [issues.md](./issues.md) |
||||
|
||||
| ID | Issue | Status | |
||||
|----|-------|--------| |
||||
| | | Open/Resolved | |
||||
|
||||
--- |
||||
|
||||
## Blocker |
||||
|
||||
| Blocker | Impact | Action | |
||||
|---------|--------|--------| |
||||
| | | | |
||||
|
||||
--- |
||||
|
||||
## Next Priority |
||||
|
||||
> Sumber kebenaran: [todo.md](./todo.md) (High Priority) |
||||
|
||||
1. {mirror 1-3 item teratas dari todo - atau cukup link} |
||||
@ -0,0 +1,93 @@
@@ -0,0 +1,93 @@
|
||||
# Server Inventory |
||||
|
||||
<!-- STRATEGY: UPDATE | Owner inventori server/infra project ini --> |
||||
<!-- READ: on-demand saat deploy, debug koneksi, atau ubah infra --> |
||||
<!-- JANGAN simpan password, private key, connection string ber-secret --> |
||||
|
||||
**Owner:** host/IP, role, aplikasi runtime, database, port, env yang dipakai **project ini**. |
||||
Indeks lintas project: monorepo root `Workspace-Context.md` (dan `SSH-HOSTS.md` jika ada) — link ke file ini, jangan duplikasi detail penuh. |
||||
|
||||
Cold start: cukup tahu path file ini dari [AGENTS.md](../AGENTS.md) / [context-index.md](./context-index.md). |
||||
|
||||
--- |
||||
|
||||
## Ringkasan |
||||
|
||||
| Field | Value | |
||||
|-------|-------| |
||||
| Project | `{path/relatif monorepo}` | |
||||
| Last updated | {YYYY-MM-DD} | |
||||
| Credential location | {vault / .env lokal — lihat .env.example} — **bukan** secret di sini | |
||||
|
||||
--- |
||||
|
||||
## Host / Server |
||||
|
||||
| Host / IP | Env | Role | OS | Akses | Catatan | |
||||
|-----------|-----|------|-----|-------|---------| |
||||
| {10.x.x.x atau hostname} | dev/staging/prod | {app / db / reverse-proxy / worker} | {Linux/Windows} | {SSH user@host / RDP} | | |
||||
|
||||
> Satu baris per host yang **benar-benar dipakai** project ini. |
||||
|
||||
--- |
||||
|
||||
## Aplikasi & Runtime per Host |
||||
|
||||
| Host / IP | Aplikasi | Jenis | Port | Path / Container | Catatan | |
||||
|-----------|----------|-------|------|------------------|---------| |
||||
| {ip} | {nama service} | Docker / nginx / IIS / Apache / systemd / Windows Service / other | {port} | {compose service / site name / unit} | | |
||||
| {ip} | {nama} | SQL Server / PostgreSQL / MySQL / Redis / other | {port} | {instance / db name} | | |
||||
|
||||
Jenis yang sering dipakai (isi yang relevan saja): |
||||
- **Web / proxy:** nginx, IIS, Apache, Caddy, Traefik |
||||
- **Runtime:** Docker, Docker Compose, Kubernetes, systemd, Windows Service |
||||
- **App:** FastAPI, Node, .NET, PHP, Java, dll. |
||||
- **Data:** SQL Server, PostgreSQL, MySQL, MariaDB, Redis, MongoDB |
||||
- **Lain:** MQTT, RabbitMQ, MinIO, dll. |
||||
|
||||
--- |
||||
|
||||
## Database |
||||
|
||||
| Host / IP | Engine | Instance / Port | Database | Dipakai untuk | Credential location | |
||||
|-----------|--------|-----------------|----------|---------------|---------------------| |
||||
| | SQL Server / PostgreSQL / ... | | | | {env var / vault} | |
||||
|
||||
--- |
||||
|
||||
## Endpoint & URL |
||||
|
||||
> Nilai runtime: variabel di .env.example (root project). **Jangan hardcode** di kode. |
||||
> Migrasi domain: [guide/migration.md](./guide/migration.md) |
||||
|
||||
| Env | URL / Host:Port | Env var | Catatan | |
||||
|-----|-----------------|--------------|---------| |
||||
| dev | | API_BASE_URL / APP_URL | | |
||||
| staging | | | | |
||||
| prod | | | | |
||||
|
||||
--- |
||||
|
||||
## Mapping ke path project (monorepo) |
||||
|
||||
| Komponen di server | Path di monorepo | Keterangan | |
||||
|--------------------|------------------|------------| |
||||
| {service / container / site} | `{path/relatif}/` | Kode / config utama | |
||||
| {nginx config / compose} | `{path}/...` | Jika config ikut di repo | |
||||
|
||||
--- |
||||
|
||||
## Dependency server ke project lain |
||||
|
||||
| Host / Service | Project monorepo | Relasi | |
||||
|----------------|------------------|--------| |
||||
| | `{path/}` | API / DB / shared network | |
||||
|
||||
--- |
||||
|
||||
## Catatan operasional |
||||
|
||||
- {firewall, VPN, ZeroTier, port expose, backup, dll. — tanpa secret} |
||||
|
||||
**Jangan:** password, API key, private key, connection string lengkap ber-credential. |
||||
**Ganti dengan:** lokasi credential + nama variabel env. |
||||
@ -0,0 +1,105 @@
@@ -0,0 +1,105 @@
|
||||
# System Requirements |
||||
|
||||
<!-- STRATEGY: UPDATE | Owner spesifikasi minimum runtime/build/deploy project ini --> |
||||
<!-- READ: on-demand saat setup baru, upgrade tool, atau migrasi server --> |
||||
|
||||
**Owner:** versi minimum OS, runtime, tool chain, dependency infra yang **wajib** agar project jalan. |
||||
Bukan duplikasi `server.md` (host/IP) — fokus **apa yang harus terpasang**, bukan di server mana. |
||||
|
||||
Credential & URL: lihat `.env.example` (root project) + [server.md](./server.md). |
||||
|
||||
--- |
||||
|
||||
## Ringkasan |
||||
|
||||
| Field | Value | |
||||
|-------|-------| |
||||
| Project | `{path/relatif monorepo}` | |
||||
| Tipe | app / api / library / infra / android | |
||||
| Last updated | {YYYY-MM-DD} | |
||||
|
||||
--- |
||||
|
||||
## Platform & OS |
||||
|
||||
| Komponen | Minimum | Direkomendasikan | Catatan | |
||||
|----------|---------|------------------|---------| |
||||
| OS dev | {Windows 11 / Ubuntu 22.04 / macOS 14} | | | |
||||
| OS server | {Linux / Windows Server} | | lihat server.md | |
||||
| Arsitektur | {x64 / arm64} | | | |
||||
|
||||
--- |
||||
|
||||
## Runtime & Toolchain |
||||
|
||||
| Tool | Versi minimum | Versi dipakai saat ini | Install / cek | |
||||
|------|---------------|------------------------|---------------| |
||||
| {Node.js / Python / JDK / .NET / Go} | | | `{command --version}` | |
||||
| {Package manager} | | | | |
||||
| {Docker / Docker Compose} | | | | |
||||
| {Android Studio / Gradle / AGP} | | | khusus Android | |
||||
| {SQL client / ODBC} | | | | |
||||
|
||||
--- |
||||
|
||||
## Dependency eksternal (wajib tersedia) |
||||
|
||||
| Dependency | Versi | Dipakai untuk | Owner docs | |
||||
|------------|-------|---------------|------------| |
||||
| {PostgreSQL / SQL Server / Redis} | | | [server.md](./server.md) | |
||||
| {nginx / IIS / Apache} | | reverse proxy | [server.md](./server.md) | |
||||
| {LDAP / Authelia / MQTT} | | | | |
||||
|
||||
--- |
||||
|
||||
## Resource minimum (server / container) |
||||
|
||||
| Lingkungan | CPU | RAM | Disk | Catatan | |
||||
|------------|-----|-----|------|---------| |
||||
| dev | | | | | |
||||
| staging | | | | | |
||||
| prod | | | | | |
||||
|
||||
--- |
||||
|
||||
## Variabel URL & konfigurasi (no hardcode) |
||||
|
||||
> Semua base URL / host / domain **harus** dari env atau config — lihat `.env.example` di root project. |
||||
|
||||
| Variabel | Wajib | Contoh (bukan production) | Dipakai oleh | |
||||
|----------|-------|---------------------------|--------------| |
||||
| `API_BASE_URL` | ya | `https://api-dev.example.com` | app client | |
||||
| `{VAR_LAIN}` | | | | |
||||
|
||||
**Aturan implementasi:** |
||||
- Jangan hardcode URL/domain/IP di source code, config commit, atau docs operasional (kecuali `.env.example` placeholder). |
||||
- Android: `BuildConfig`, `gradle.properties`, network security config — bukan string literal di `.kt`. |
||||
- Backend: baca dari environment / `.env` (lokal, gitignore). |
||||
|
||||
--- |
||||
|
||||
## Port & protokol |
||||
|
||||
| Service | Port | Protokol | Catatan | |
||||
|---------|------|----------|---------| |
||||
| | | HTTP/HTTPS/TCP | | |
||||
|
||||
--- |
||||
|
||||
## Checklist setup baru (developer / server) |
||||
|
||||
- [ ] Penuhi runtime minimum di tabel di atas |
||||
- [ ] Copy `.env.example` -> `.env` (lokal, jangan commit `.env`) |
||||
- [ ] Isi URL sesuai env (dev/staging/prod) |
||||
- [ ] Verifikasi koneksi ke dependency di [server.md](./server.md) |
||||
- [ ] Smoke test sesuai [guide/migration.md](./guide/migration.md) jika migrasi |
||||
|
||||
--- |
||||
|
||||
## Perubahan requirement |
||||
|
||||
Setiap upgrade tool major, OS baru, atau dependency baru: |
||||
1. Update file ini |
||||
2. Update [version.md](./version.md) + [changelog.md](./changelog.md) |
||||
3. Update `.env.example` jika variabel URL berubah |
||||
4. Migrasi server/domain: ikuti [guide/migration.md](./guide/migration.md) |
||||
@ -0,0 +1,42 @@
@@ -0,0 +1,42 @@
|
||||
# TODO |
||||
|
||||
<!-- STRATEGY: ACTIVE UPDATE | Priority aktif = single owner di file ini --> |
||||
|
||||
> Last updated: {YYYY-MM-DD} |
||||
> Sesi terakhir: [ai-session-summary.md](./ai-session-summary.md) |
||||
|
||||
**Owner:** daftar pekerjaan aktif (High / Medium / Low) dan technical debt actionable. |
||||
Dokumen lain hanya merujuk ke sini — jangan menduplikasi daftar priority. |
||||
|
||||
--- |
||||
|
||||
## High Priority |
||||
|
||||
- [ ] {task} - {catatan singkat} |
||||
|
||||
--- |
||||
|
||||
## Medium Priority |
||||
|
||||
- [ ] {task} |
||||
|
||||
--- |
||||
|
||||
## Low Priority |
||||
|
||||
- [ ] {task} |
||||
|
||||
--- |
||||
|
||||
## Technical Debt |
||||
|
||||
- [ ] {debt item} - {prioritas} |
||||
|
||||
--- |
||||
|
||||
## Selesai (Sesi Ini) |
||||
|
||||
<!-- OVERWRITE tiap sesi — jangan menumpuk history lintas sesi. |
||||
Riwayat permanen: changelog.md + version.md --> |
||||
|
||||
- [x] {task} - selesai {YYYY-MM-DD} |
||||
@ -0,0 +1,29 @@
@@ -0,0 +1,29 @@
|
||||
# Version History |
||||
|
||||
<!-- STRATEGY: APPEND | Satu entri per perbaikan/perubahan — jangan overwrite entri lama --> |
||||
|
||||
**Owner:** riwayat versi repo dalam bentuk poin-poin per rilis/perubahan. |
||||
Setiap perbaikan atau perubahan kode/config yang material **wajib** menambah entri di sini. |
||||
|
||||
**Wajib update sebelum deploy** (install ke device, push server, rilis APK/binary, cutover prod): |
||||
1. Naikkan versi di source of truth build (`build.gradle.kts`, `package.json`, `pyproject.toml`, dll.) |
||||
2. **Append** entri baru di file ini — bullet poin jelas (apa diubah, mengapa, QC jika ada) |
||||
3. Jangan overwrite entri lama (strategi **APPEND**) |
||||
|
||||
Gunakan semver jika memungkinkan (`MAJOR.MINOR.PATCH`), atau tanggal+urutan (`YYYY.MM.DD.N`) jika belum ada skema versi. |
||||
|
||||
Sinkron dengan [changelog.md](./changelog.md): changelog = kategori Keep a Changelog; file ini = ringkasan berpoin per versi. |
||||
|
||||
--- |
||||
|
||||
## [x.y.z] - {YYYY-MM-DD} |
||||
|
||||
- {perubahan 1} |
||||
- {perubahan 2} |
||||
- {perubahan 3} |
||||
|
||||
--- |
||||
|
||||
## [0.1.0] - {YYYY-MM-DD} |
||||
|
||||
- Inisialisasi dokumentasi standar repo |
||||
@ -0,0 +1,156 @@
@@ -0,0 +1,156 @@
|
||||
# Workspace Context |
||||
|
||||
<!-- STRATEGY: UPDATE JARANG | Konteks global monorepo --> |
||||
|
||||
> Workspace ini adalah **monorepo** (satu git root, banyak subproject). |
||||
> "Repository" = **subproject** (folder project), bukan git repo terpisah. |
||||
> Sesi hari ini: [Workspace-Session.md](./Workspace-Session.md) |
||||
> Standar: `AI-Agent-Standards/` |
||||
|
||||
--- |
||||
|
||||
## Overview |
||||
|
||||
| Field | Value | |
||||
|-------|-------| |
||||
| Workspace | {NAMA_WORKSPACE} | |
||||
| Tipe | Monorepo | |
||||
| Root Git | `{path-root}` | |
||||
| Remote | `{url}` | |
||||
| Owner | {nama/team} | |
||||
| Last updated | {YYYY-MM-DD} | |
||||
|
||||
--- |
||||
|
||||
## Urutan baca AI (hemat token) |
||||
|
||||
``` |
||||
1. Workspace-Session.md <- Active focus dulu |
||||
2. {project}/AGENTS.md <- cold start (~200-400 token) |
||||
3. {project}/docs/ai-session-summary.md <- TL;DR + Lanjut + Jangan |
||||
4. STOP - mulai kerja |
||||
5. On-demand: todo, issues, api, guide, server.md, context-index, adr |
||||
``` |
||||
|
||||
**Target cold start: < 2000 token.** |
||||
|
||||
**Jangan baca di cold start:** changelog penuh, version history, WORKLOG, development-log, seluruh context-index. |
||||
|
||||
**Rolling session memory per project = hanya** `docs/ai-session-summary.md`. |
||||
|
||||
--- |
||||
|
||||
## Read budget |
||||
|
||||
| Tujuan | Baca maksimal | |
||||
|--------|----------------| |
||||
| Lanjut task yang sama | AGENTS + ai-session-summary | |
||||
| Ambil task baru | + todo.md (High) | |
||||
| Debug | + issues.md (ID terkait) | |
||||
| Ubah API | + docs/api/ | |
||||
| Ikuti prosedur / flow | + docs/guide/ | |
||||
| Deploy / debug koneksi / infra | + docs/server.md | |
||||
| Arsitektur | + docs/adr/ | |
||||
| Navigasi domain | + context-index.md (Zona B) | |
||||
|
||||
--- |
||||
|
||||
## Project Index |
||||
|
||||
| Project | Path | Deskripsi | Cold start | Context | |
||||
|---------|------|-----------|------------|---------| |
||||
| {name} | `{path/}` | | [`AGENTS.md`]({path}/AGENTS.md) | [`docs/context-index.md`]({path}/docs/context-index.md) | |
||||
|
||||
### Shared resources (bukan project) |
||||
|
||||
| Folder | Fungsi | |
||||
|--------|--------| |
||||
| | | |
||||
|
||||
--- |
||||
|
||||
## Dependency antar project |
||||
|
||||
| From | To | Tipe | Catatan | |
||||
|------|-----|------|---------| |
||||
| | | | | |
||||
|
||||
--- |
||||
|
||||
## Single owner (anti-duplikasi) |
||||
|
||||
| Informasi | Owner | |
||||
|-----------|-------| |
||||
| Cold start / aturan kritis | `{project}/AGENTS.md` | |
||||
| Narasi sesi (rolling) | `{project}/docs/ai-session-summary.md` | |
||||
| Priority / TODO | `{project}/docs/todo.md` | |
||||
| Bug / RCA | `{project}/docs/issues.md` | |
||||
| Changelog | `{project}/docs/changelog.md` | |
||||
| Poin versi | `{project}/docs/version.md` | |
||||
| API | `{project}/docs/api/` | |
||||
| Flow / step-by-step | `{project}/docs/guide/` | |
||||
| Server / IP / runtime / DB | `{project}/docs/server.md` | |
||||
| System requirements | `{project}/docs/system-requirements.md` | |
||||
| URL/env template | `{project}/.env.example` | |
||||
| Migrasi server/domain | `{project}/docs/guide/migration.md` | |
||||
| Peta domain (on-demand) | `{project}/docs/context-index.md` | |
||||
| Lintas project sesi | `Workspace-Session.md` | |
||||
| Peta monorepo stabil | `Workspace-Context.md` | |
||||
|
||||
Arsip (bukan jalur wajib): WORKLOG, development-log. |
||||
|
||||
--- |
||||
|
||||
## Tier handover |
||||
|
||||
### Tier 1 - Minimal |
||||
|
||||
1. OVERWRITE `docs/ai-session-summary.md` (max 80 baris; TL;DR + Lanjut + Jangan) |
||||
2. UPDATE `docs/todo.md` |
||||
3. APPEND `docs/changelog.md` + `docs/version.md` |
||||
4. UPDATE `AGENTS.md` hanya jika aturan kritis berubah |
||||
|
||||
### Tier 2 - Jika relevan |
||||
|
||||
issues, adr, guide, server.md, system-requirements.md, .env.example, guide/migration.md, project-status, context-index, api/ |
||||
|
||||
### Tier 3 - Monorepo |
||||
|
||||
OVERWRITE `Workspace-Session.md` (wajib **Active focus**) |
||||
|
||||
--- |
||||
|
||||
## Environment global |
||||
|
||||
| Env | Catatan | |
||||
|-----|---------| |
||||
| dev | | |
||||
|
||||
Credential: {vault/path} - jangan simpan secret. |
||||
|
||||
--- |
||||
|
||||
## Server Index (lintas project) |
||||
|
||||
> Indeks saja. Detail per project: `{project}/docs/server.md`. |
||||
> Inventori host bersama juga boleh di `SSH-HOSTS.md` — tetap link ke server.md project terkait. |
||||
|
||||
| Host / IP | Project monorepo | Role | Runtime ringkas | Detail | |
||||
|-----------|------------------|------|-----------------|--------| |
||||
| {10.x.x.x} | `{path}` | app/db/proxy | Docker, nginx, SQL Server, ... | [server.md]({path}/docs/server.md) | |
||||
|
||||
Satu host boleh muncul di beberapa project jika di-share; detail role per project tetap di `docs/server.md` masing-masing. |
||||
|
||||
--- |
||||
|
||||
## Standar dan perintah |
||||
|
||||
Standar: `AI-Agent-Standards/` |
||||
|
||||
| Perintah | Aksi | |
||||
|----------|------| |
||||
| `/handover` | Full tiered preservation | |
||||
| `/session-summary` | Overwrite ai-session-summary.md | |
||||
| `/workspace-summary` | Overwrite Workspace-Session.md | |
||||
|
||||
Pengetahuan penting, arsitektur, flow, **dan inventori server (IP + runtime)** yang disepakati **tidak boleh** hanya di chat AI. |
||||
@ -0,0 +1,71 @@
@@ -0,0 +1,71 @@
|
||||
# Workspace Session |
||||
|
||||
<!-- STRATEGY: OVERWRITE | Ringkasan lintas-project sesi ini (monorepo) --> |
||||
<!-- READ: baca Active focus dulu; detail project on-demand via link --> |
||||
<!-- BATAS: max ~50 baris / ~100 baris jika banyak project --> |
||||
|
||||
--- |
||||
|
||||
## Active focus |
||||
|
||||
<!-- 1-3 baris per project yang dikerjakan - agent scan ini dulu --> |
||||
|
||||
- `{path}`: {status singkat} -> next: {prioritas langsung} |
||||
- `{path}`: {status singkat} -> next: {prioritas langsung} |
||||
|
||||
--- |
||||
|
||||
## Session Information |
||||
|
||||
| Field | Value | |
||||
|-------|-------| |
||||
| Tanggal | {YYYY-MM-DD} | |
||||
| Session ID | {YYYY-MM-DD-judul} | |
||||
| AI Agent | {Cursor/Cline/dll} | |
||||
| Developer | {nama jika ada} | |
||||
|
||||
--- |
||||
|
||||
## Executive Summary |
||||
|
||||
- {max 5 bullet lintas project} |
||||
|
||||
--- |
||||
|
||||
## Project yang dikerjakan |
||||
|
||||
| Project | Path | Summary | Branch | Version | |
||||
|---------|------|---------|--------|---------| |
||||
| | `{path/}` | | | {x.y.z} | |
||||
|
||||
--- |
||||
|
||||
## Cross-Project Impact |
||||
|
||||
| Perubahan | Project | Dampak ke Project Lain | |
||||
|-----------|---------|------------------------| |
||||
| | | | |
||||
|
||||
--- |
||||
|
||||
## Referensi detail (on-demand) |
||||
|
||||
| Project | Cold start | Session | Version | |
||||
|---------|------------|---------|---------| |
||||
| | [`AGENTS.md`]({path}/AGENTS.md) | [`ai-session-summary.md`]({path}/docs/ai-session-summary.md) | [`version.md`]({path}/docs/version.md) | |
||||
|
||||
--- |
||||
|
||||
## Next Priority (workspace) |
||||
|
||||
> Detail: masing-masing `docs/todo.md` |
||||
|
||||
1. {priority lintas-project} |
||||
|
||||
--- |
||||
|
||||
## Catatan lintas-project |
||||
|
||||
- {max 5 bullet} |
||||
|
||||
**Konteks stabil:** [Workspace-Context.md](./Workspace-Context.md) |
||||
@ -0,0 +1,33 @@
@@ -0,0 +1,33 @@
|
||||
# ArcGIS Enterprise — .env.example (template, aman di-commit) |
||||
# Salin ke .env lalu isi username & password |
||||
|
||||
# ============================================================================= |
||||
# SQL Server — main-db 10.100.1.25 |
||||
# ============================================================================= |
||||
MSSQL_HOST=10.100.1.25 |
||||
MSSQL_PORT=1433 |
||||
MSSQL_DATABASE=master |
||||
MSSQL_USERNAME=sa |
||||
MSSQL_PASSWORD=change-me |
||||
MSSQL_ENCRYPT=false |
||||
MSSQL_TRUST_SERVER_CERTIFICATE=true |
||||
|
||||
# ============================================================================= |
||||
# PostgreSQL — main-db 10.100.1.25 |
||||
# ============================================================================= |
||||
POSTGRES_HOST=10.100.1.25 |
||||
POSTGRES_PORT=5432 |
||||
POSTGRES_DATABASE=geonetagent_dev |
||||
POSTGRES_USERNAME=geonet_collector |
||||
POSTGRES_PASSWORD=change-me |
||||
|
||||
# DATABASE_URL=postgresql://geonet_collector:change-me@10.100.1.25:5432/geonetagent_dev |
||||
|
||||
# ============================================================================= |
||||
# ArcGIS topology |
||||
# ============================================================================= |
||||
ARCGIS_BASE_HOST=10.100.1.51 |
||||
ARCGIS_PORTAL_URL=https://dev.gisportal.id/portal |
||||
ARCGIS_SERVER_HOST=10.100.1.51 |
||||
ARCGIS_DS_OBJECT_HOST=10.100.1.52 |
||||
ARCGIS_DS_SPATIO_HOST=10.100.1.53 |
||||
@ -0,0 +1,32 @@
@@ -0,0 +1,32 @@
|
||||
# AGENTS.md — Cold Start |
||||
|
||||
> Project: ArcGIS Enterprise/ |
||||
> Sesi: [docs/ai-session-summary.md](./docs/ai-session-summary.md) |
||||
> Peta: [docs/context-index.md](./docs/context-index.md) |
||||
|
||||
## Apa ini? |
||||
|
||||
ESRI ArcGIS Enterprise dev — Portal, Server, Web Adaptor, Data Stores |
||||
|
||||
## Aturan kritis |
||||
|
||||
- dev.gisportal.id DNS langsung ke .51 — bypass reverse proxy |
||||
- No commit license / credential ESRI |
||||
- Perubahan topology → append docs/version.md + ADR |
||||
- **No hardcoded URL** — .env.example |
||||
|
||||
- No commit kecuali user minta |
||||
- Pengetahuan penting wajib ke docs |
||||
|
||||
## Lanjut kerja |
||||
|
||||
1. AGENTS.md → docs/ai-session-summary.md → STOP |
||||
2. docs/server.md, docs/todo.md |
||||
|
||||
## Pointer |
||||
|
||||
| Butuh | Buka | |
||||
|-------|------| |
||||
| Versi | [docs/version.md](./docs/version.md) | |
||||
| Server | [docs/server.md](./docs/server.md) | |
||||
| Migrasi | [docs/guide/migration.md](./docs/guide/migration.md) | |
||||
@ -0,0 +1,109 @@
@@ -0,0 +1,109 @@
|
||||
# ArcGIS Enterprise — ArcGIS Base Development |
||||
|
||||
**Terakhir diaudit:** 6 Jul 2026 |
||||
|
||||
## Akses SSH |
||||
|
||||
```text |
||||
ssh dev51-base |
||||
ssh Administrator@10.100.1.51 -p 22 |
||||
``` |
||||
|
||||
- Key: `~/.ssh/id_ed25519_geonet_proxmox` |
||||
- Login key-only (passwordless) via `C:\ProgramData\ssh\administrators_authorized_keys` |
||||
|
||||
## Identitas Server |
||||
|
||||
| Item | Nilai | |
||||
|------|-------| |
||||
| Hostname | DEV11 | |
||||
| IP | 10.100.1.51 | |
||||
| OS | Windows Server 2016 Standard (build 10.0.14393) | |
||||
| RAM | 128 GB | |
||||
| Disk C: | 511 GB — terpakai ~37% (320 GB free) | |
||||
| Hypervisor | Proxmox (Virtio-win drivers terpasang) | |
||||
|
||||
## Stack ArcGIS Enterprise (utama) |
||||
|
||||
| Komponen | Versi | Status | |
||||
|----------|-------|--------| |
||||
| Portal for ArcGIS | 12.0.58905 | Running | |
||||
| ArcGIS Server | 12.0.58905 | Running | |
||||
| ArcGIS Data Store (Relational) | 12.0.58905 | Running | |
||||
| ArcGIS Web Adaptor (IIS) | 11.4 & 12.0 | Terpasang | |
||||
| ArcGIS Pro | 3.5.57366 | Terpasang | |
||||
| ArcGIS Insights | 2023.3.0.5972 | Terpasang | |
||||
| ArcGIS Monitor | 2023.3.1 | Running (agent) | |
||||
|
||||
**Direktori ArcGIS:** `C:\Program Files\ArcGIS\{Portal,Server,DataStore,Monitor}` |
||||
|
||||
### IIS — Web Adaptor (Default Web Site, port 80/443) |
||||
|
||||
| Path | App Pool | |
||||
|------|----------| |
||||
| `/portal` | ArcGISWebAdaptorAppPoolportal | |
||||
| `/server` | ArcGISWebAdaptorAppPoolserver | |
||||
| `/image` | ArcGISWebAdaptorAppPoolimage | |
||||
| `/notebook` | ArcGISWebAdaptorAppPoolnotebook | |
||||
| `/notebooksvr` | ArcGISWebAdaptorAppPoolnotebooksvr | |
||||
| `/workflow` | ArcGISWebAdaptorAppPoolworkflow | |
||||
| `/knowledge` | ArcGISWebAdaptorAppPoolknowledge | |
||||
| `/geoevent` | ArcGISWebAdaptorAppPoolgeoevent | |
||||
| `/exbapp` | DefaultAppPool (Experience Builder) | |
||||
|
||||
### Service ArcGIS yang berjalan |
||||
|
||||
- Portal for ArcGIS |
||||
- ArcGIS Server |
||||
- ArcGIS Data Store |
||||
- ArcGIS Monitor Agent |
||||
|
||||
## Aplikasi Non-Bawaan Windows (lainnya) |
||||
|
||||
### Development |
||||
|
||||
| Aplikasi | Versi | Catatan | |
||||
|----------|-------|---------| |
||||
| Laragon | 5.0.0 | `C:\laragon` — PHP 7.4, MySQL 5.7, Apache 2.4, Node 14, Redis, Memcached | |
||||
| DBeaver | 7.3.3 | DB client | |
||||
| SQL Server Management Studio | 18.5.1 | | |
||||
| Integration Services (SSIS) | 15.0 | | |
||||
| .NET SDK | 8.0.302 | + ASP.NET Core Hosting Bundle 6.0 & 8.0 | |
||||
| ODBC Driver 17 / OLE DB Driver | 17.5 / 18.3 | SQL Server connectivity | |
||||
| SQL Server 2012 Native Client | 11.4 | | |
||||
|
||||
### Utilitas & Monitoring |
||||
|
||||
| Aplikasi | Versi | |
||||
|----------|-------| |
||||
| Google Chrome | 149.0.7827.201 | |
||||
| Notepad++ | 8.4.2 | |
||||
| WinRAR | 5.70 | |
||||
| MiniTool Partition Wizard | 12.1.0 | |
||||
| Zabbix Agent | 6.2.1 (port 10050) | |
||||
| OpenSSH Server | 10.0 (port 22) | |
||||
| Microsoft Web Deploy | 4.0 | |
||||
|
||||
## Port Penting |
||||
|
||||
| Port | Proses | Fungsi | |
||||
|------|--------|--------| |
||||
| 22 | sshd | SSH | |
||||
| 80 / 443 | IIS | Web Adaptor | |
||||
| 6099 | ArcGISServer | Server internal | |
||||
| 7099 | ArcGISPortal | Portal internal | |
||||
| 9099 | ArcGISDataStore | Data Store internal | |
||||
| 7654, 9876 | postgres | PostgreSQL (Data Store) | |
||||
| 10050 | zabbix_agentd | Monitoring | |
||||
|
||||
## Fitur Windows Bawaan (relevan) |
||||
|
||||
- IIS (Web Server, ASP.NET 4.6, Windows Auth, WebSocket) |
||||
- .NET Framework 3.5 & 4.6 |
||||
- Windows Defender, PowerShell 5.1, File Server / SMB |
||||
|
||||
## Catatan |
||||
|
||||
- Server berperan sebagai **ArcGIS Enterprise Base Development** lengkap (Portal + Server + Data Store + Web Adaptor). |
||||
- Tambahan di luar docs awal: ArcGIS Pro, Insights, Monitor, dan Laragon (dev stack PHP/MySQL). |
||||
- Banyak instance **ArcSOC** aktif — normal untuk ArcGIS Server dengan banyak service/geoprocessing. |
||||
@ -0,0 +1,3 @@
@@ -0,0 +1,3 @@
|
||||
# ADR template |
||||
|
||||
Salin untuk keputusan arsitektur baru. |
||||
@ -0,0 +1,14 @@
@@ -0,0 +1,14 @@
|
||||
# AI Session Summary |
||||
|
||||
`yaml |
||||
session: 2026-07-06-init |
||||
project: ArcGIS Enterprise/ |
||||
version: 0.1.0 |
||||
status: ready |
||||
next: Lengkapi operasional dari server live |
||||
` |
||||
|
||||
## TL;DR |
||||
|
||||
- Bootstrap docs AI-Agent-Standards untuk infra ArcGIS Enterprise |
||||
- Host utama: 10.100.1.51 (dev.gisportal.id) |
||||
@ -0,0 +1,6 @@
@@ -0,0 +1,6 @@
|
||||
# Changelog — ArcGIS Enterprise |
||||
|
||||
## [0.1.0] - 2026-07-06 |
||||
|
||||
### Added |
||||
- Struktur dokumentasi AI-Agent-Standards |
||||
@ -0,0 +1,20 @@
@@ -0,0 +1,20 @@
|
||||
# Context Index — ArcGIS Enterprise |
||||
|
||||
## Zona A |
||||
|
||||
| Item | Value | |
||||
|------|-------| |
||||
| Path | ArcGIS Enterprise/ | |
||||
| Cold start | [../AGENTS.md](../AGENTS.md) | |
||||
| Versi | 0.1.0 — [version.md](./version.md) | |
||||
| Stack | Windows Server, IIS, ArcGIS Enterprise | |
||||
| Tipe | infra | |
||||
| Last updated | 2026-07-06 | |
||||
|
||||
## Zona B |
||||
|
||||
| Dokumen | Path | |
||||
|---------|------| |
||||
| Server | [server.md](./server.md) | |
||||
| Todo | [todo.md](./todo.md) | |
||||
| Migrasi | [guide/migration.md](./guide/migration.md) | |
||||
@ -0,0 +1,3 @@
@@ -0,0 +1,3 @@
|
||||
# Guides |
||||
|
||||
- [migration.md](./migration.md) |
||||
@ -0,0 +1,11 @@
@@ -0,0 +1,11 @@
|
||||
# Migration Guide |
||||
|
||||
## Topology |
||||
|
||||
| Host | Role | |
||||
|------|------| |
||||
| 10.100.1.51 | Portal, Server, DS Relational, IIS | |
||||
| 10.100.1.52 | Data Store Object | |
||||
| 10.100.1.53 | Data Store Spatio | |
||||
|
||||
DNS: dev.gisportal.id → 10.100.1.51 (tidak lewat nginx .24) |
||||
@ -0,0 +1,3 @@
@@ -0,0 +1,3 @@
|
||||
# Issues |
||||
|
||||
Belum ada issue terdokumentasi. |
||||
@ -0,0 +1,8 @@
@@ -0,0 +1,8 @@
|
||||
# Project Status — ArcGIS Enterprise |
||||
|
||||
ESRI ArcGIS Enterprise dev — Portal, Server, Web Adaptor, Data Stores |
||||
|
||||
| Item | Status | |
||||
|------|--------| |
||||
| Dokumentasi bootstrap | Done 2026-07-06 | |
||||
| Operasional | Lihat server.md | |
||||
@ -0,0 +1,29 @@
@@ -0,0 +1,29 @@
|
||||
# Server — ArcGIS Enterprise |
||||
|
||||
> **Last updated:** 2026-07-06 |
||||
|
||||
## Topology |
||||
|
||||
| Host | IP | Role | |
||||
|------|-----|------| |
||||
| ArcGIS Base | `10.100.1.51` | Portal, Server, Web Adaptor, DS Relational, IIS | |
||||
| DS Object | `10.100.1.52` | Data Store Object | |
||||
| DS Spatio | `10.100.1.53` | Data Store Spatio | |
||||
|
||||
## DNS |
||||
|
||||
| Domain | Routing | |
||||
|--------|---------| |
||||
| `dev.gisportal.id` | Langsung `10.100.1.51` — **bypass** nginx `.24` | |
||||
| Publik | `117.102.73.100` → NAT `10.100.1.51:443` | |
||||
|
||||
## SSH aliases |
||||
|
||||
```bash |
||||
ssh dev51-base # 10.100.1.51 |
||||
ssh dev13-object # 10.100.1.52 (verify alias di server-audit/host.md) |
||||
``` |
||||
|
||||
Detail: `ARCHITECTURE.md`, `server-audit/host.md` § ArcGIS. |
||||
|
||||
**Aturan:** perubahan topology → ADR + version.md. |
||||
@ -0,0 +1,8 @@
@@ -0,0 +1,8 @@
|
||||
# System Requirements — ArcGIS Enterprise |
||||
|
||||
| Field | Value | |
||||
|-------|-------| |
||||
| Stack | Windows Server, IIS, ArcGIS Enterprise | |
||||
| Host | 10.100.1.51 | |
||||
|
||||
Env: [../.env.example](../.env.example) |
||||
@ -0,0 +1,9 @@
@@ -0,0 +1,9 @@
|
||||
# TODO — ArcGIS Enterprise |
||||
|
||||
## High |
||||
|
||||
- [ ] Verifikasi config live vs dokumentasi repo |
||||
|
||||
## Selesai |
||||
|
||||
- [x] Bootstrap AI-Agent-Standards 2026-07-06 |
||||
@ -0,0 +1,6 @@
@@ -0,0 +1,6 @@
|
||||
# Version History |
||||
|
||||
## [0.1.0] - 2026-07-06 |
||||
|
||||
- Bootstrap dokumentasi AI-Agent-Standards |
||||
- Topology dari ARCHITECTURE.md: .51 base, .52 object DS, .53 spatio DS |
||||
@ -0,0 +1,6 @@
@@ -0,0 +1,6 @@
|
||||
# Dockge — .env.example |
||||
DOCKGE_PRIMARY_URL=https://dockge.gisportal.id |
||||
DOCKGE_PRIMARY_HOST=10.100.1.24 |
||||
DOCKGE_STACKS_PATH=/opt/stacks |
||||
DOCKGE_AGENT_MAILCOW_HOST=10.100.1.28 |
||||
DOCKGE_AGENT_MAILCOW_PORT=5001 |
||||
@ -0,0 +1,33 @@
@@ -0,0 +1,33 @@
|
||||
# AGENTS.md — Cold Start |
||||
|
||||
> Project: Dockge/ |
||||
> Sesi: [docs/ai-session-summary.md](./docs/ai-session-summary.md) |
||||
> Peta: [docs/context-index.md](./docs/context-index.md) |
||||
|
||||
## Apa ini? |
||||
|
||||
Docker stack manager — dockge.gisportal.id; primary .24 + agents remote |
||||
|
||||
## Aturan kritis |
||||
|
||||
- Stack path standar: /opt/stacks/{nama} |
||||
- Agent remote: port 5001 (LAN only) |
||||
- Deploy stack → append docs/version.md |
||||
- No commit secret compose .env |
||||
- **No hardcoded URL** — .env.example |
||||
|
||||
- No commit kecuali user minta |
||||
- Pengetahuan penting wajib ke docs |
||||
|
||||
## Lanjut kerja |
||||
|
||||
1. AGENTS.md → docs/ai-session-summary.md → STOP |
||||
2. docs/server.md, docs/todo.md |
||||
|
||||
## Pointer |
||||
|
||||
| Butuh | Buka | |
||||
|-------|------| |
||||
| Versi | [docs/version.md](./docs/version.md) | |
||||
| Server | [docs/server.md](./docs/server.md) | |
||||
| Migrasi | [docs/guide/migration.md](./docs/guide/migration.md) | |
||||
@ -0,0 +1,3 @@
@@ -0,0 +1,3 @@
|
||||
# ADR template |
||||
|
||||
Salin untuk keputusan arsitektur baru. |
||||
@ -0,0 +1,14 @@
@@ -0,0 +1,14 @@
|
||||
# AI Session Summary |
||||
|
||||
`yaml |
||||
session: 2026-07-06-init |
||||
project: Dockge/ |
||||
version: 1.5.0 |
||||
status: ready |
||||
next: Lengkapi operasional dari server live |
||||
` |
||||
|
||||
## TL;DR |
||||
|
||||
- Bootstrap docs AI-Agent-Standards untuk infra Dockge |
||||
- Host utama: 10.100.1.24 (dockge.gisportal.id) |
||||
@ -0,0 +1,6 @@
@@ -0,0 +1,6 @@
|
||||
# Changelog — Dockge |
||||
|
||||
## [1.5.0] - 2026-07-06 |
||||
|
||||
### Added |
||||
- Struktur dokumentasi AI-Agent-Standards |
||||
@ -0,0 +1,20 @@
@@ -0,0 +1,20 @@
|
||||
# Context Index — Dockge |
||||
|
||||
## Zona A |
||||
|
||||
| Item | Value | |
||||
|------|-------| |
||||
| Path | Dockge/ | |
||||
| Cold start | [../AGENTS.md](../AGENTS.md) | |
||||
| Versi | 1.5.0 — [version.md](./version.md) | |
||||
| Stack | Dockge v1.5.0, /opt/stacks/ | |
||||
| Tipe | infra | |
||||
| Last updated | 2026-07-06 | |
||||
|
||||
## Zona B |
||||
|
||||
| Dokumen | Path | |
||||
|---------|------| |
||||
| Server | [server.md](./server.md) | |
||||
| Todo | [todo.md](./todo.md) | |
||||
| Migrasi | [guide/migration.md](./guide/migration.md) | |
||||
@ -0,0 +1,3 @@
@@ -0,0 +1,3 @@
|
||||
# Guides |
||||
|
||||
- [migration.md](./migration.md) |
||||
@ -0,0 +1,12 @@
@@ -0,0 +1,12 @@
|
||||
# Migration Guide |
||||
|
||||
## Stacks |
||||
|
||||
Semua stack Docker production di /opt/stacks/ pada host terkait. |
||||
|
||||
| Host | Role | |
||||
|------|------| |
||||
| 10.100.1.24 | Dockge primary + mayoritas stack | |
||||
| 10.100.1.28 | Dockge agent (Mailcow) | |
||||
|
||||
Migrasi stack: export compose + volume backup → deploy di host baru → update nginx. |
||||
@ -0,0 +1,3 @@
@@ -0,0 +1,3 @@
|
||||
# Issues |
||||
|
||||
Belum ada issue terdokumentasi. |
||||
@ -0,0 +1,8 @@
@@ -0,0 +1,8 @@
|
||||
# Project Status — Dockge |
||||
|
||||
Docker stack manager — dockge.gisportal.id; primary .24 + agents remote |
||||
|
||||
| Item | Status | |
||||
|------|--------| |
||||
| Dokumentasi bootstrap | Done 2026-07-06 | |
||||
| Operasional | Lihat server.md | |
||||
@ -0,0 +1,45 @@
@@ -0,0 +1,45 @@
|
||||
# Server — Dockge |
||||
|
||||
> **Last updated:** 2026-07-06 |
||||
|
||||
## Primary (`.24`) |
||||
|
||||
| Item | Nilai | |
||||
|------|-------| |
||||
| URL | `https://dockge.gisportal.id` | |
||||
| Host | `10.100.1.24` | |
||||
| Stacks path | `/opt/stacks/` | |
||||
| Versi | Dockge v1.5.0 | |
||||
|
||||
## Remote agent (Mailcow `.28`) |
||||
|
||||
| Item | Nilai | |
||||
|------|-------| |
||||
| Agent URL | `http://10.100.1.28:5001` | |
||||
| Stack | `/opt/stacks/mailcow` | |
||||
| Firewall | port 5001 dari `.24` saja | |
||||
|
||||
--- |
||||
|
||||
## Stacks utama (`/opt/stacks/`) |
||||
|
||||
| Stack | Host | Repo docs | |
||||
|-------|------|-----------| |
||||
| geonet-console | `.24` | server-connection | |
||||
| zammad | `.24` | Zammad | |
||||
| mailcow | `.28` | Mailcow | |
||||
| geonet-collector | `.24` | GeoNetAgent | |
||||
| databaselist | `.24` | server-connection | |
||||
|
||||
Setiap deploy stack → append [version.md](./version.md) di repo terkait. |
||||
|
||||
--- |
||||
|
||||
## SSH |
||||
|
||||
```bash |
||||
ssh reverse-proxy # .24 primary |
||||
ssh mailcow # .28 agent |
||||
``` |
||||
|
||||
Credential: env server — jangan di docs. |
||||
@ -0,0 +1,8 @@
@@ -0,0 +1,8 @@
|
||||
# System Requirements — Dockge |
||||
|
||||
| Field | Value | |
||||
|-------|-------| |
||||
| Stack | Dockge v1.5.0, /opt/stacks/ | |
||||
| Host | 10.100.1.24 | |
||||
|
||||
Env: [../.env.example](../.env.example) |
||||
@ -0,0 +1,9 @@
@@ -0,0 +1,9 @@
|
||||
# TODO — Dockge |
||||
|
||||
## High |
||||
|
||||
- [ ] Verifikasi config live vs dokumentasi repo |
||||
|
||||
## Selesai |
||||
|
||||
- [x] Bootstrap AI-Agent-Standards 2026-07-06 |
||||
@ -0,0 +1,10 @@
@@ -0,0 +1,10 @@
|
||||
# Version History |
||||
|
||||
## [1.5.0] - 2026-07-06 |
||||
|
||||
- Bootstrap dokumentasi AI-Agent-Standards |
||||
- Primary Dockge di .24; agent Mailcow .28:5001 |
||||
|
||||
## [1.5.0-deploy] - 2026-07-03 |
||||
|
||||
- Dockge agent terpasang di VM Mailcow |
||||
@ -1,84 +1,41 @@
@@ -1,84 +1,41 @@
|
||||
# AGENTS.md — AI Agent Rules |
||||
# AGENTS.md — Cold Start |
||||
|
||||
## Entry Point Wajib |
||||
> Project: `GeoNetAgent/` |
||||
> Sesi terakhir: [docs/ai-session-summary.md](./docs/ai-session-summary.md) |
||||
> Peta lengkap: [docs/context-index.md](./docs/context-index.md) |
||||
> Env template: [.env.example](./.env.example) |
||||
|
||||
Sebelum melakukan pekerjaan apa pun, baca berurutan: |
||||
1. `docs/context-index.md` — peta seluruh dokumentasi |
||||
2. `.cursor/blueprint.md` — visi, fase, batas modul |
||||
3. `.cursor/progress.md` — fase aktif & checklist DoD |
||||
4. Dokumen spesifik modul (db-schema, api-contracts, dll) |
||||
## Apa ini? |
||||
|
||||
**Jangan implement fase N+1 jika fase N belum DoD.** |
||||
IT asset monitoring & CMDB ringan: Windows PowerShell agent → FastAPI collector → PostgreSQL. Melengkapi Zabbix. |
||||
|
||||
--- |
||||
## Aturan kritis |
||||
|
||||
## Aturan Kode |
||||
- **No hardcoded URL/domain/IP** — baca dari `.env` / `.env.example` |
||||
- Jangan commit `.env`; credentials di server saja |
||||
- No commit kecuali user minta eksplisit |
||||
- **Deploy agent:** bump `agent/VERSION` + append [docs/version.md](./docs/version.md) + publish script |
||||
- Jangan implement fase N+1 jika fase N belum DoD (`.cursor/progress.md`) |
||||
- SSH butuh approval user; SCP pakai `-o "MACs=hmac-sha1"` dari Windows |
||||
- Pengetahuan penting **wajib ke docs**, bukan chat |
||||
|
||||
### Python (FastAPI Collector) |
||||
- Gunakan `snake_case` untuk variable, function, file |
||||
- Type hints wajib di semua function signature |
||||
- Pydantic schema di `app/schemas/` — jangan inline model di routes |
||||
- Route di `app/api/` — satu file per resource |
||||
- DB session via dependency injection (`get_db`) |
||||
- Jangan commit `.env` — gunakan `.env.example` |
||||
## Lanjut kerja |
||||
|
||||
### PowerShell (Agent) |
||||
- Module di `agent/lib/` — satu file per sensor (Get-CpuInfo.ps1, dll) |
||||
- Jangan hardcode credential di skrip |
||||
- Hindari literal `$env:` di file `.ps1` yang di-serve Nginx (nginx potong respons) |
||||
- Test lokal dulu sebelum publish ke `agent.gisportal.id/install/` |
||||
|
||||
### SQL / Database |
||||
- PK: UUID (`gen_random_uuid()`) |
||||
- Timestamp: `timestamptz` |
||||
- Nama tabel: `snake_case` plural |
||||
- Setiap perubahan schema → update `docs/database.md` + `.cursor/db-schema.md` |
||||
- Migration order: lihat `infra/db/README.md` |
||||
|
||||
--- |
||||
|
||||
## Aturan Deploy |
||||
|
||||
**Wajib setelah bump versi agent:** |
||||
```powershell |
||||
.\infra\collector\publish_agent_install.ps1 # upload ke agent.gisportal.id/install/ |
||||
.\infra\collector\push_collector.ps1 # rebuild UI/API jika berubah |
||||
``` |
||||
1. AGENTS.md |
||||
2. docs/ai-session-summary.md |
||||
3. STOP |
||||
4. On-demand: docs/todo.md, docs/issues.md, .cursor/blueprint.md, docs/server.md |
||||
``` |
||||
|
||||
- Update `agent/VERSION` + `agent/install/manifest.json` sebelum publish |
||||
- Update `Riwayat milestone` di `.cursor/progress.md` |
||||
- Update `Sync terakhir` di `perintah.md` |
||||
|
||||
**File transfer ke server:** gunakan `scp -o "MACs=hmac-sha1"` dari Windows. |
||||
Jangan heredoc SSH dari PowerShell — `$` variabel terpotong. |
||||
|
||||
--- |
||||
|
||||
## Aturan Dokumentasi |
||||
|
||||
- Setiap perubahan arsitektur → buat ADR baru di `docs/adr/ADR-00N-*.md` |
||||
- ADR **tidak boleh dihapus** — buat ADR baru jika keputusan berubah |
||||
- Setelah implementasi: update `.cursor/progress.md` + `perintah.md` |
||||
- Implementasi tanpa dokumentasi = **belum selesai** |
||||
- Update `docs/context-index.md` jika ada dokumen baru |
||||
|
||||
--- |
||||
|
||||
## Aturan Keamanan |
||||
|
||||
- **Jangan commit secret**: password DB, bearer token, API key |
||||
- Credentials DB ada di `/root/geonetagent_dev.credentials` di server 10.100.1.25 |
||||
- Token agent ada di `.env` server — lihat `docs/environment.md` untuk nama variabelnya |
||||
- SSH command butuh approval user sebelum dijalankan |
||||
- Nginx `agent.gisportal.id`: `ssi off` — jangan taruh `$env:` literal di file `.ps1` yang di-serve |
||||
|
||||
--- |
||||
Detail kode: `.cursor/rules` equivalent via `.cursor/blueprint.md`, `docs/development.md`. |
||||
|
||||
## Batas Sistem (Non-goals) |
||||
## Pointer cepat |
||||
|
||||
Jangan implement hal-hal berikut — sudah diputuskan di ADR/blueprint: |
||||
- ❌ Engine monitoring time-series (pakai Zabbix) |
||||
- ❌ NMS pengganti MikroTik/Proxmox tools |
||||
- ❌ Duplikasi data GIS legacy dari SQL Server |
||||
- ❌ Remote desktop / RMM agent |
||||
- ❌ Ticketing enterprise penuh (fase awal) |
||||
| Butuh | Buka | |
||||
|-------|------| |
||||
| Priority | [docs/todo.md](./docs/todo.md) | |
||||
| Versi / deploy | [docs/version.md](./docs/version.md) | |
||||
| Server | [docs/server.md](./docs/server.md) | |
||||
| Schema DB | [docs/database.md](./docs/database.md) | |
||||
| ADR | [docs/adr/](./docs/adr/) | |
||||
|
||||
@ -0,0 +1,25 @@
@@ -0,0 +1,25 @@
|
||||
# AI Session Summary |
||||
|
||||
```yaml |
||||
session: 2026-07-06-docs-bootstrap |
||||
project: GeoNetAgent/ |
||||
version: 0.1.12-phase0 |
||||
status: ready |
||||
next: Lanjutkan fase aktif di .cursor/progress.md |
||||
agent: Cursor |
||||
``` |
||||
|
||||
## TL;DR |
||||
|
||||
- Bootstrap docs AI-Agent-Standards: version.md, system-requirements.md, guide/, ai-session-summary |
||||
- Agent live `v0.1.12-phase0`; collector di `10.100.1.24` |
||||
|
||||
## Lanjut dari sini |
||||
|
||||
1. Baca `.cursor/progress.md` untuk fase aktif |
||||
2. Bump versi agent → append `docs/version.md` + publish |
||||
|
||||
## Jangan |
||||
|
||||
- Jangan hardcode credential di skrip PowerShell |
||||
- Jangan commit `.env` |
||||
@ -0,0 +1,21 @@
@@ -0,0 +1,21 @@
|
||||
# Changelog — GeoNetAgent |
||||
|
||||
Ringkasan per versi: [version.md](./version.md). |
||||
|
||||
--- |
||||
|
||||
## [Unreleased] |
||||
|
||||
--- |
||||
|
||||
## [0.1.12-phase0] - 2026-06-29 |
||||
|
||||
### Changed |
||||
- Agent sensors & manifest update |
||||
|
||||
--- |
||||
|
||||
## [0.1.0] - 2026-07-06 |
||||
|
||||
### Added |
||||
- Bootstrap AI-Agent-Standards (version.md, system-requirements.md, guide/) |
||||
@ -0,0 +1,6 @@
@@ -0,0 +1,6 @@
|
||||
# Guides — GeoNetAgent |
||||
|
||||
| Guide | Path | Kapan | |
||||
|-------|------|-------| |
||||
| Migrasi server/domain | [migration.md](./migration.md) | Pindah collector/nginx | |
||||
| Deploy | [../deployment.md](../deployment.md) | Install stack | |
||||
@ -0,0 +1,19 @@
@@ -0,0 +1,19 @@
|
||||
# Migration Guide — GeoNetAgent |
||||
|
||||
Inventori: [../server.md](../server.md). Env: [../../.env.example](../../.env.example). |
||||
|
||||
## Host saat ini |
||||
|
||||
| Komponen | Host | |
||||
|----------|------| |
||||
| Collector + nginx | `10.100.1.24` | |
||||
| PostgreSQL | `10.100.1.25` | |
||||
| Agent install URL | `agent.gisportal.id` | |
||||
|
||||
## Checklist migrasi |
||||
|
||||
1. Deploy collector ke host baru |
||||
2. Update DNS/nginx → `collector.gisportal.id`, `agent.gisportal.id` |
||||
3. Update `.env` + `agent/install` manifest URL |
||||
4. Re-publish agent (`publish_agent_install.ps1`) |
||||
5. Append [../version.md](../version.md) |
||||
@ -0,0 +1,26 @@
@@ -0,0 +1,26 @@
|
||||
# System Requirements — GeoNetAgent |
||||
|
||||
| Field | Value | |
||||
|-------|-------| |
||||
| Project | `GeoNetAgent/` | |
||||
| Tipe | app (agent + API) | |
||||
| Last updated | 2026-07-06 | |
||||
|
||||
## Runtime |
||||
|
||||
| Tool | Minimum | Dipakai | |
||||
|------|---------|---------| |
||||
| Python | 3.11+ | FastAPI collector | |
||||
| PostgreSQL | 15+ | `10.100.1.25` | |
||||
| Docker | 24+ | Collector stack `.24` | |
||||
| PowerShell | 5.1+ | Windows agent | |
||||
| nginx | 1.24+ | `agent.gisportal.id` | |
||||
|
||||
## Variabel env (no hardcode) |
||||
|
||||
| Variabel | Contoh | File | |
||||
|----------|--------|------| |
||||
| `COLLECTOR_API_URL` | `https://collector.gisportal.id` | `.env.example` | |
||||
| `DATABASE_URL` | PostgreSQL `.25` | collector `.env` | |
||||
|
||||
Detail: [environment.md](./environment.md), [server.md](./server.md). |
||||
@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
|
||||
# Version History |
||||
|
||||
**Owner:** riwayat versi deploy GeoNetAgent. Append per perubahan material. |
||||
|
||||
--- |
||||
|
||||
## [0.1.12-phase0] - 2026-06-29 |
||||
|
||||
- Agent version bump (lihat `agent/VERSION`) |
||||
- Collector/nginx di `10.100.1.24` |
||||
|
||||
--- |
||||
|
||||
## [0.1.0] - 2026-06-15 |
||||
|
||||
- Bootstrap dokumentasi AI-Agent-Standards (version.md, guide/, system-requirements.md) |
||||
- Agent phase0 foundation |
||||
|
||||
--- |
||||
|
||||
## [0.1.0-docs] - 2026-06-01 |
||||
|
||||
- Inisialisasi dokumentasi repo (`docs/`, ADR-001–003) |
||||
@ -0,0 +1,58 @@
@@ -0,0 +1,58 @@
|
||||
# AGENTS.md — Cold Start |
||||
|
||||
> Project: `Mailcow/` |
||||
> Sesi terakhir: [docs/ai-session-summary.md](./docs/ai-session-summary.md) |
||||
> Peta lengkap: [docs/context-index.md](./docs/context-index.md) |
||||
> Env template: [.env.example](./.env.example) |
||||
|
||||
## Apa ini? |
||||
|
||||
Self-hosted mail server (Mailcow dockerized) untuk `geonet.co.id` + `gisportal.id`. Inbox canonical di `sync.geonet.co.id`; POP3 drain cPanel (geonet); `gisportal.id` langsung ke Mailcow tanpa cPanel. |
||||
|
||||
## Aturan kritis |
||||
|
||||
- **No hardcoded URL/domain/IP** — baca dari `.env` / `docs/environment.md` |
||||
- Copy `.env.example` → `.env` lokal; **jangan commit** `.env` |
||||
- No commit kecuali user minta eksplisit |
||||
- **Deploy / rilis:** append [docs/version.md](./docs/version.md) (poin perubahan) + [docs/changelog.md](./docs/changelog.md) |
||||
- `support@geonet.co.id` = **authsource ldap** (password AD); fetchmail POP3 tetap dari hosting |
||||
- SSH ke server **wajib persetujuan user** (`ssh mailcow` → `10.100.1.28`) |
||||
- Pengetahuan penting **wajib ke docs**, bukan hanya chat |
||||
|
||||
## Lanjut kerja (urutan baca) |
||||
|
||||
``` |
||||
1. AGENTS.md <- Anda di sini |
||||
2. docs/ai-session-summary.md <- TL;DR + Lanjut + Jangan |
||||
3. STOP - mulai kerja |
||||
4. On-demand: |
||||
- docs/todo.md |
||||
- docs/issues.md |
||||
- docs/guide/outlook-imap-setup.md |
||||
- docs/guide/migration.md |
||||
- docs/system-requirements.md |
||||
- docs/server.md |
||||
- .env.example |
||||
- docs/context-index.md |
||||
``` |
||||
|
||||
**Rolling session memory = hanya** `docs/ai-session-summary.md`. |
||||
|
||||
## Pointer cepat |
||||
|
||||
| Butuh | Buka | |
||||
|-------|------| |
||||
| Priority | [docs/todo.md](./docs/todo.md) | |
||||
| Versi / deploy | [docs/version.md](./docs/version.md) | |
||||
| Bug / RCA | [docs/issues.md](./docs/issues.md) | |
||||
| IMAP client (Outlook) | [docs/guide/outlook-imap-setup.md](./docs/guide/outlook-imap-setup.md) | |
||||
| Migrasi MX/domain | [docs/guide/migration.md](./docs/guide/migration.md) | |
||||
| Multi-domain gisportal.id | [docs/notes/gisportal-id-mail.md](./docs/notes/gisportal-id-mail.md) | |
||||
| Hybrid cPanel geonet | [docs/notes/hybrid-migration-cpanel-mailcow.md](./docs/notes/hybrid-migration-cpanel-mailcow.md) | |
||||
| System requirements | [docs/system-requirements.md](./docs/system-requirements.md) | |
||||
| Server / infra | [docs/server.md](./docs/server.md) | |
||||
| Env vars | [docs/environment.md](./docs/environment.md) | |
||||
|
||||
## Multi-project |
||||
|
||||
`Workspace-Context.md` → `AGENTS.md` → `docs/ai-session-summary.md` |
||||
@ -0,0 +1,25 @@
@@ -0,0 +1,25 @@
|
||||
# ADR-000: Template |
||||
|
||||
> Salin file ini sebagai `ADR-NNN-judul-keputusan.md` saat ada keputusan arsitektur baru. |
||||
|
||||
## Status |
||||
|
||||
Proposed | Accepted | Deprecated | Superseded |
||||
|
||||
## Konteks |
||||
|
||||
{Masalah atau kebutuhan} |
||||
|
||||
## Keputusan |
||||
|
||||
{Apa yang diputuskan} |
||||
|
||||
## Konsekuensi |
||||
|
||||
- Positif: ... |
||||
- Negatif: ... |
||||
- Risiko: ... |
||||
|
||||
## Referensi |
||||
|
||||
- [context-index.md](../context-index.md) |
||||
@ -0,0 +1,29 @@
@@ -0,0 +1,29 @@
|
||||
# ADR-0001: support@ authsource LDAP |
||||
|
||||
## Status |
||||
|
||||
Accepted — 2026-07-06 |
||||
|
||||
## Konteks |
||||
|
||||
- `support@geonet.co.id` perlu diakses user via IMAP dengan **password AD** |
||||
- Inbound email SSOT masih cPanel (MX) → fetchmail POP3 drain ke Mailcow |
||||
- Mailbox sebelumnya `authsource=mailcow` (service account SQL) |
||||
|
||||
## Keputusan |
||||
|
||||
**Satu mailbox** `support@geonet.co.id` dengan `authsource=ldap`: |
||||
- fetchmail tetap deliver ke alamat yang sama (tidak terpengaruh auth) |
||||
- User PC: IMAP `sync.geonet.co.id:993` + password AD |
||||
- Tidak membuat mailbox kedua; tidak copy/move inbox |
||||
|
||||
## Konsekuensi |
||||
|
||||
- Positif: satu password AD untuk user; inbox tetap canonical di Mailcow |
||||
- Perhatian: SOGo perlu verifikasi setelah switch (`_sogo_static_view`) |
||||
- fetchmail POP3 password tetap password **cPanel** (terpisah dari LDAP) |
||||
- Zammad channel: gunakan password AD atau app password (dokumentasikan di Zammad) |
||||
|
||||
## Implementasi |
||||
|
||||
Script: `scripts/switch-support-to-ldap.sh` |
||||
Binary file not shown.
@ -1,15 +1,44 @@
@@ -1,15 +1,44 @@
|
||||
# Changelog — Mailcow |
||||
|
||||
Format [Keep a Changelog](https://keepachangelog.com/). Ringkasan: [version.md](./version.md). |
||||
|
||||
--- |
||||
|
||||
## [1.2.5] - 2026-07-06 |
||||
|
||||
### Changed |
||||
- SPF `gisportal.id` di Master Web: `v=spf1 a mx ~all` → `v=spf1 ip4:117.102.73.102 -all` |
||||
|
||||
### Verified |
||||
- Propagasi SPF di `dns1.masterweb.com` OK |
||||
|
||||
--- |
||||
|
||||
## 2026-07-03 — fetchmail, SOGo, outbound relay |
||||
## [1.2.4] - 2026-07-06 |
||||
|
||||
**Ringkasan:** Email flow support@geonet.co.id end-to-end via Mailcow. |
||||
### Added |
||||
- Domain `gisportal.id` (Mailcow murni) + `admin@gisportal.id` |
||||
- `docs/notes/gisportal-id-mail.md` |
||||
- Scripts: `fix-sogo-domain.sh`, `setup-gisportal-inbound-whitelist.sh` |
||||
|
||||
**Fitur:** fetchmail POP3 drain; relay cPanel :587; SOGo operational. |
||||
### Fixed |
||||
- SOGo Unauthorized (`_sogo_static_view`); inbound forwarding hosts whitelist |
||||
|
||||
**Fix:** SOGo Unauthorized; Gmail 550 smarthost. |
||||
--- |
||||
|
||||
## [1.2.3] - 2026-07-06 |
||||
|
||||
### Added |
||||
- Transport map Jalur B `rbsetiawan@` → cPanel `:587` |
||||
- `scripts/setup-transport-cpanel-user.sh` |
||||
|
||||
### Verified |
||||
- `support@` → `rbsetiawan@` (cPanel) OK |
||||
|
||||
--- |
||||
|
||||
**File:** scripts/install-fetchmail-support.sh, docs/* |
||||
## Planned |
||||
|
||||
**Author:** AI Agent (Cursor) |
||||
- DKIM `gisportal.id` + `geonet.co.id` |
||||
- Zammad IMAP/SMTP channel |
||||
- MX cutover geonet.co.id |
||||
@ -1,149 +1,88 @@
@@ -1,149 +1,88 @@
|
||||
# Context Index — Mailcow ⭐ AI Entry Point |
||||
# Context Index — Mailcow |
||||
|
||||
> **Terakhir Diperbarui:** 2026-07-03 |
||||
> **Fase Aktif:** Fase 1 — Mailcow live, transisi MX cPanel → sync 📧 |
||||
|
||||
**Sesi terakhir:** [docs/ai-session-summary.md](./ai-session-summary.md) |
||||
> Cold start: [../AGENTS.md](../AGENTS.md) → [ai-session-summary.md](./ai-session-summary.md) → **STOP** |
||||
|
||||
--- |
||||
|
||||
## Filosofi |
||||
|
||||
Proyek ini menerapkan **AI Native Development**: |
||||
- Repository = sumber kebenaran utama (Single Source of Truth) |
||||
- AI tidak boleh mengandalkan riwayat percakapan |
||||
- Developer sering berpindah perangkat — konteks harus tersimpan di repo |
||||
- Implementasi tanpa dokumentasi = belum selesai |
||||
## Zona A — Always-read pointers |
||||
|
||||
| Item | Value | |
||||
|------|-------| |
||||
| Nama | Mailcow | |
||||
| Path monorepo | `Mailcow/` | |
||||
| Cold start | [../AGENTS.md](../AGENTS.md) | |
||||
| Sesi terakhir | [ai-session-summary.md](./ai-session-summary.md) | |
||||
| Priority | [todo.md](./todo.md) | |
||||
| Server / infra | [server.md](./server.md) | |
||||
| System requirements | [system-requirements.md](./system-requirements.md) | |
||||
| Env template | [../.env.example](../.env.example) | |
||||
| Versi | **1.2.5** — [version.md](./version.md) | |
||||
| Stack | Mailcow dockerized, fetchmail (geonet), Dovecot/Postfix | |
||||
| Domains | `geonet.co.id` (hybrid cPanel), `gisportal.id` (murni) | |
||||
| Tipe | infra | |
||||
| Last updated | 2026-07-06 | |
||||
|
||||
**Rolling session memory:** hanya [ai-session-summary.md](./ai-session-summary.md). |
||||
|
||||
--- |
||||
|
||||
## Urutan Membaca |
||||
## Zona B — On-demand map |
||||
|
||||
1. **File ini** — peta navigasi |
||||
2. **`docs/ai-session-summary.md`** — ringkasan sesi terakhir ⭐ |
||||
3. `docs/environment.md` — variabel `.env` (tanpa secret) |
||||
3. `.env.example` → copy ke `.env` — isi password & secret |
||||
4. Dokumen spesifik task (lihat tabel di bawah) |
||||
5. `Zammad/docs/context-index.md` — integrasi email channel |
||||
|
||||
--- |
||||
### Dokumentasi inti |
||||
|
||||
## Posisi dalam Super Apps |
||||
| Dokumen | Kapan baca | |
||||
|---------|------------| |
||||
| [project-status.md](./project-status.md) | Status milestone | |
||||
| [issues.md](./issues.md) | Bug / RCA | |
||||
| [changelog.md](./changelog.md) | Audit riwayat | |
||||
| [version.md](./version.md) | Deploy / rilis | |
||||
| [environment.md](./environment.md) | Variabel env | |
||||
| [deployment.md](./deployment.md) | Install stack | |
||||
| [guide/](./guide/) | IMAP user, migrasi MX | |
||||
|
||||
``` |
||||
Internet → MX geonet.co.id → cPanel (staging, inbox kosong setelah POP3) |
||||
│ |
||||
fetchmail POP3 + delete (VM .27) |
||||
▼ |
||||
Mailcow sync.geonet.co.id — inbox canonical (IMAP) |
||||
│ │ |
||||
Outlook user Zammad |
||||
IMAP+SMTP sync IMAP+SMTP sync |
||||
``` |
||||
### Notes (domain) |
||||
|
||||
| Repo terkait | Entry point | Kapan baca | |
||||
|--------------|-------------|------------| |
||||
| **Zammad** | `Zammad/docs/context-index.md` | Channel email inbound/outbound | |
||||
| **server-connection** | `server-connection/docs/context-index.md` | LDAP AD, nginx pattern | |
||||
| **mysupperapps_FE_PWA** | `docs/context-index.md` | Mail UI `/mail` (fase berikutnya) | |
||||
| Dokumen | Isi | |
||||
|---------|-----| |
||||
| [notes/gisportal-id-mail.md](./notes/gisportal-id-mail.md) | Domain `gisportal.id` — Mailcow murni, DNS Master Web | |
||||
| [notes/hybrid-migration-cpanel-mailcow.md](./notes/hybrid-migration-cpanel-mailcow.md) | Jalur A/B hybrid geonet | |
||||
| [notes/ldap-ad-mailcow.md](./notes/ldap-ad-mailcow.md) | LDAP AD + SOGo troubleshooting | |
||||
| [notes/storage-nas-qnap.md](./notes/storage-nas-qnap.md) | Backup QNAP | |
||||
| [notes/deployment-sizing.md](./notes/deployment-sizing.md) | Sizing VM | |
||||
|
||||
--- |
||||
### Parent / sibling |
||||
|
||||
## Peta Dokumentasi |
||||
|
||||
### `docs/` — Flat Files |
||||
|
||||
| File | Isi | Status | Baca Saat | |
||||
|------|-----|--------|-----------| |
||||
| `docs/context-index.md` | **File ini** — navigasi | ✅ | Selalu | |
||||
| `docs/environment.md` | Env vars, port, integrasi Zammad | ✅ | Setup, deploy | |
||||
| `docs/project-status.md` | Status modul, milestone | ✅ | Planning | |
||||
| `docs/ai-session-summary.md` | **Ringkasan sesi terakhir** | ✅ | Lanjut kerja | |
||||
| `docs/roadmap.md` | Fase Mailcow dalam super apps | 📋 | Planning | |
||||
| `docs/todo.md` | Next actions berprioritas | ✅ | Sebelum coding | |
||||
| `docs/changelog.md` | Riwayat perubahan penting | ✅ | Referensi | |
||||
| `docs/issues.md` | Known bugs + workaround | ✅ | Debug | |
||||
| `docs/server.md` | Server, SSH, spec VM `.28` | ✅ | Deploy | |
||||
| `docs/deployment.md` | Step-by-step install Mailcow | ✅ | Deploy | |
||||
| `docs/security.md` | Credential, DNS, port 25 | 📋 | Security | |
||||
|
||||
### `docs/notes/` |
||||
|
||||
| File | Isi | |
||||
|------|-----| |
||||
| `email-sync-migration-concept.md` | **Konsep sync hosting → Mailcow → Zammad** (MX tetap cPanel) | |
||||
| `zammad-email-channel.md` | Step-by-step SMTP + IMAP Zammad ↔ Mailcow | |
||||
| `dns-cutover-geonet-co-id.md` | MX, SPF, DKIM, DMARC cutover dari cPanel | |
||||
| `storage-nas-qnap.md` | **Email di NAS QNAP** — iSCSI / NFS / backup | |
||||
| `deployment-sizing.md` | **Linux + Docker, spec VM 30+ user** | |
||||
| `ldap-ad-mailcow.md` | **LDAP AD → Mailcow** — auth + provisioning user terpusat | |
||||
|
||||
### Root repo |
||||
|
||||
| File | Isi | |
||||
|------|-----| |
||||
| `.env.example` | Template konfigurasi — **aman di-commit** | |
||||
| `.env` | Nilai aktual (password) — **gitignored** | |
||||
| `.gitignore` | Exclude secret & data Mailcow | |
||||
| `scripts/install-fetchmail-support.sh` | Install POP3 drain + systemd timer | |
||||
| Repo | Entry | |
||||
|------|-------| |
||||
| Zammad | `Zammad/docs/context-index.md` | |
||||
| server-connection | `server-connection/docs/context-index.md` | |
||||
| nginx | `nginx/docs/context-index.md` | |
||||
| Dockge | `Dockge/docs/context-index.md` | |
||||
|
||||
--- |
||||
|
||||
## Quick Reference |
||||
## Arsitektur singkat |
||||
|
||||
| Fungsi | URL / Path | |
||||
|--------|------------| |
||||
| Mailcow UI (target) | `https://sync.geonet.co.id` | |
||||
| Hostname mail | `sync.geonet.co.id` | |
||||
| Mailbox support (fase sync) | `support@sync.geonet.co.id` | |
||||
| Mailbox produksi (hosting) | `support@geonet.co.id` @ cPanel | |
||||
| Domain utama | `geonet.co.id` (MX tetap hosting) | |
||||
| Docker stack (target) | `/opt/stacks/mailcow/` | |
||||
| Server Mailcow | `10.100.1.28` (16 vCPU, 32 GB, 2×512 GB SSD) | |
||||
| Server Zammad | `10.100.1.24` | |
||||
|
||||
### Port layanan |
||||
|
||||
| Port | Layanan | |
||||
|------|---------| |
||||
| 25 | SMTP inbound | |
||||
| 465 | SMTPS | |
||||
| 587 | Submission (Zammad outbound) | |
||||
| 993 | IMAPS (Zammad inbound) | |
||||
| 443 | HTTPS Web UI | |
||||
|
||||
### SSH |
||||
|
||||
```bash |
||||
ssh mailcow # 10.100.1.28 |
||||
``` |
||||
geonet.co.id → MX cPanel → fetchmail POP3 → Mailcow (hybrid, transport maps) |
||||
gisportal.id → MX mail.gisportal.id → 117.102.73.102 → Mailcow (murni) |
||||
├── Outlook IMAP :993 / SMTP :587 (sync.geonet.co.id) |
||||
└── Zammad IMAP (planned) |
||||
``` |
||||
|
||||
> SSH ke server **wajib minta persetujuan user** sebelum dijalankan. |
||||
|
||||
--- |
||||
|
||||
## Status saat ini (2026-07-03) |
||||
|
||||
| Item | Status | |
||||
|------|--------| |
||||
| Mailcow stack `/opt/stacks/mailcow` | ✅ | |
||||
| Domain `geonet.co.id` + DKIM generated | ✅ | |
||||
| fetchmail POP3 drain `support@` | ✅ timer 2 menit | |
||||
| Outbound relay cPanel `:587` | ✅ transisi | |
||||
| SOGo kirim/terima `support@` | ✅ verified user | |
||||
| LDAP IdP (user AD lain) | ✅ | |
||||
| Zammad → Mailcow channel | ❌ | |
||||
| DKIM/SPF DNS publish | ❌ | |
||||
| MX cutover ke sync | ❌ | |
||||
|
||||
Detail: [project-status.md](./project-status.md) |
||||
| Fungsi | URL / Host | |
||||
|--------|------------| |
||||
| Mailcow UI | `https://sync.geonet.co.id` | |
||||
| VM | `10.100.1.28` | |
||||
| IMAP/SMTP | `sync.geonet.co.id` :993 / :587 | |
||||
| DNS gisportal | Master Web (`dns1.masterweb.com`) | |
||||
|
||||
--- |
||||
|
||||
## Aturan Utama AI |
||||
## Aturan kritis AI |
||||
|
||||
1. Baca `docs/context-index.md` ini terlebih dahulu |
||||
2. **Jangan commit** `.env` — hanya update `.env.example` (placeholder) dan `docs/environment.md` |
||||
3. Integrasi Zammad → referensi `Zammad/docs/` — jangan duplikasi panjang |
||||
4. LDAP umum → referensi `server-connection/docs/environment.md` |
||||
5. Setelah deploy → buat/update `docs/deployment.md` + `docs/project-status.md` |
||||
- No commit `.env`; update `.env.example` + `environment.md` |
||||
- Deploy material → append `version.md` + `changelog.md` |
||||
- `support@` = authsource **ldap**; `admin@gisportal.id` = **mailcow** |
||||
- Jangan masukkan user ke `Mail-Users` jika masih baca cPanel |
||||
- SSH wajib persetujuan user |
||||
|
||||
@ -0,0 +1,14 @@
@@ -0,0 +1,14 @@
|
||||
# Guides — Mailcow |
||||
|
||||
**Owner:** runbook operasional Mailcow. |
||||
|
||||
## Indeks |
||||
|
||||
| Guide | Path | Kapan dipakai | |
||||
|-------|------|---------------| |
||||
| IMAP/SMTP Outlook user | [outlook-imap-setup.md](./outlook-imap-setup.md) | Setup email di PC user | |
||||
| Migrasi MX / domain | [migration.md](./migration.md) | Cutover cPanel → Mailcow | |
||||
| Deploy Mailcow | [../deployment.md](../deployment.md) | Install / reinstall stack | |
||||
| Email sync concept | [../notes/email-sync-migration-concept.md](../notes/email-sync-migration-concept.md) | Arsitektur POP3 drain | |
||||
| Zammad channel | [../notes/zammad-email-channel.md](../notes/zammad-email-channel.md) | Integrasi ticketing | |
||||
| LDAP AD | [../notes/ldap-ad-mailcow.md](../notes/ldap-ad-mailcow.md) | User AD → mailbox | |
||||
@ -0,0 +1,91 @@
@@ -0,0 +1,91 @@
|
||||
# Migration Guide — Mailcow (MX & Domain) |
||||
|
||||
**Owner:** cutover email `geonet.co.id` dari cPanel ke Mailcow. |
||||
Inventori: [../server.md](../server.md). Env: [../../.env.example](../../.env.example). |
||||
|
||||
**Prinsip:** URL/domain dynamic via `.env` — bukan hardcode di script. |
||||
|
||||
--- |
||||
|
||||
## Status migrasi saat ini (2026-07-06) |
||||
|
||||
| Fase | Status | Keterangan | |
||||
|------|--------|------------| |
||||
| Mailcow live | ✅ | VM `10.100.1.28`, `sync.geonet.co.id` | |
||||
| POP3 drain | ✅ | fetchmail timer 2 menit, `nokeep` | |
||||
| Outbound relay | ✅ Transisi | cPanel SMTP :587 | |
||||
| MX DNS | ❌ | Masih cPanel | |
||||
| DKIM/SPF publish | ❌ | Key generated, belum DNS | |
||||
| fetchmail mati | ❌ | Setelah MX cutover | |
||||
|
||||
--- |
||||
|
||||
## Inventori sebelum cutover MX |
||||
|
||||
| Item | Saat ini | Target | File update | |
||||
|------|----------|--------|-------------| |
||||
| MX record | cPanel | `sync.geonet.co.id` | DNS panel | |
||||
| Inbox canonical | Mailcow (via POP3) | Mailcow (langsung) | — | |
||||
| SPF | cPanel IP | Mailcow `117.102.73.102` | DNS | |
||||
| DKIM | — | Mailcow selector | DNS | |
||||
| PTR | TBD | `sync.geonet.co.id` | Provider IP | |
||||
| fetchmail | aktif | **stop** | systemd disable | |
||||
| relay cPanel | aktif | opsional mati | Mailcow relayhosts | |
||||
|
||||
--- |
||||
|
||||
## Fase 1 — Transisi (saat ini) |
||||
|
||||
1. MX tetap cPanel |
||||
2. fetchmail POP3 drain → Mailcow inbox |
||||
3. User Outlook → IMAP `sync.geonet.co.id:993` saja |
||||
4. Outbound relay cPanel sampai reputasi IP Mailcow OK |
||||
|
||||
Verifikasi fetchmail: |
||||
```bash |
||||
ssh mailcow |
||||
systemctl status fetchmail-support.timer |
||||
tail -20 /var/log/fetchmail-support.log |
||||
``` |
||||
|
||||
--- |
||||
|
||||
## Fase 2 — DNS email publish |
||||
|
||||
1. [ ] Ambil DKIM public key: Mailcow Admin → Configuration → DKIM |
||||
2. [ ] Publish TXT DKIM di DNS `geonet.co.id` |
||||
3. [ ] Update SPF: `v=spf1 ip4:117.102.73.102 include:... -all` |
||||
4. [ ] Tambah DMARC (opsional): `_dmarc.geonet.co.id` |
||||
5. [ ] PTR `117.102.73.102` → `sync.geonet.co.id` |
||||
6. [ ] Smoke test: kirim ke Gmail, cek header SPF/DKIM pass |
||||
|
||||
Append [../version.md](../version.md) setelah publish. |
||||
|
||||
--- |
||||
|
||||
## Fase 3 — MX cutover |
||||
|
||||
1. [ ] Stabil minimal 2–4 minggu (fetchmail + relay tanpa error) |
||||
2. [ ] Turunkan TTL MX 24 jam sebelumnya |
||||
3. [ ] Ubah MX → `sync.geonet.co.id` (priority 10) |
||||
4. [ ] Monitor Postfix log Mailcow 24–48 jam |
||||
5. [ ] `systemctl disable --now fetchmail-support.timer` |
||||
6. [ ] Evaluasi matikan relay cPanel (kirim langsung dari Mailcow) |
||||
7. [ ] Update docs: server.md, project-status.md, version.md |
||||
|
||||
--- |
||||
|
||||
## Rollback MX |
||||
|
||||
1. Kembalikan MX ke cPanel |
||||
2. Enable fetchmail timer jika masih diperlukan |
||||
3. Catat di [../issues.md](../issues.md) |
||||
|
||||
--- |
||||
|
||||
## Riwayat migrasi |
||||
|
||||
| Tanggal | Dari | Ke | Versi | Catatan | |
||||
|---------|------|-----|-------|---------| |
||||
| 2026-07-03 | — | POP3 drain live | 1.0.0 | fetchmail + relay | |
||||
| 2026-07-06 | — | Docs bootstrap | 1.1.0 | SSOT AI-Agent-Standards | |
||||
@ -0,0 +1,77 @@
@@ -0,0 +1,77 @@
|
||||
# Guide — Outlook IMAP/SMTP ke Mailcow |
||||
|
||||
**Untuk:** PC user yang memakai `support@geonet.co.id` (atau mailbox `@geonet.co.id` lain). |
||||
**Server:** Mailcow `sync.geonet.co.id` — **bukan** `mail.geonet.co.id` (cPanel). |
||||
|
||||
--- |
||||
|
||||
## Pengaturan |
||||
|
||||
| Setting | Nilai | |
||||
|---------|-------| |
||||
| Email / Username | `support@geonet.co.id` | |
||||
| Password | Password **Active Directory** (Windows login `support` / `support@geonet.co.id`) | |
||||
| Incoming | IMAP | |
||||
| Server IMAP | `sync.geonet.co.id` | |
||||
| Port IMAP | `993` | |
||||
| Enkripsi IMAP | SSL/TLS | |
||||
| Outgoing | SMTP | |
||||
| Server SMTP | `sync.geonet.co.id` | |
||||
| Port SMTP | `587` (STARTTLS) — **bukan** SSL/TLS di port 587 | |
||||
| Alternatif SMTP | Port `465` + **SSL/TLS** (jika 587 gagal) | |
||||
| Auth SMTP | Ya — sama dengan IMAP | |
||||
|
||||
> `support@` pakai **authsource ldap** (grup AD `Mail-Users`, atribut `mail`). Inbound tetap via fetchmail POP3 dari hosting. |
||||
|
||||
--- |
||||
|
||||
## Outlook (Windows) |
||||
|
||||
1. **File → Add Account** → **Advanced setup** → **IMAP** |
||||
2. Incoming: `sync.geonet.co.id`, port **993**, SSL/TLS |
||||
3. Outgoing: `sync.geonet.co.id`, port **587**, STARTTLS |
||||
4. **More settings → Outgoing Server:** centang SMTP requires authentication, use same as incoming |
||||
5. Hapus akun lama jika masih `mail.geonet.co.id` |
||||
|
||||
--- |
||||
|
||||
## Thunderbird |
||||
|
||||
Manual config: IMAP 993 SSL, SMTP 587 STARTTLS, Normal password, username email penuh. |
||||
|
||||
--- |
||||
|
||||
## Alur email masuk (transisi) |
||||
|
||||
``` |
||||
Internet → MX cPanel → inbox cPanel |
||||
↓ fetchmail POP3 (~2 menit) |
||||
inbox Mailcow → Outlook (IMAP) |
||||
``` |
||||
|
||||
User **tidak** perlu setting POP3 di PC — hanya IMAP ke Mailcow. |
||||
|
||||
--- |
||||
|
||||
## Troubleshooting |
||||
|
||||
| Gejala | Cek | |
||||
|--------|-----| |
||||
| Auth gagal | Password **AD** (bukan password Mailcow lama); pastikan user di grup `Mail-Users` | |
||||
| SMTP encryption error | Port **587** harus **STARTTLS** (bukan SSL/TLS). Port **465** pakai SSL/TLS | |
||||
| Cert error / encryption failed | Pastikan cert Let's Encrypt terpasang (`scripts/sync-ssl-from-nginx.sh`) | |
||||
| Email tidak masuk | MX masih cPanel — cek fetchmail: `tail /var/log/fetchmail-support.log` | |
||||
| Port blocked | `Test-NetConnection sync.geonet.co.id -Port 993` | |
||||
|
||||
Detail server: [../server.md](../server.md), [../issues.md](../issues.md). |
||||
|
||||
--- |
||||
|
||||
## Verifikasi koneksi (PowerShell) |
||||
|
||||
```powershell |
||||
Test-NetConnection sync.geonet.co.id -Port 993 |
||||
Test-NetConnection sync.geonet.co.id -Port 587 |
||||
``` |
||||
|
||||
Keduanya harus `TcpTestSucceeded : True`. |
||||
@ -1,23 +1,19 @@
@@ -1,23 +1,19 @@
|
||||
# Issues — Mailcow |
||||
|
||||
--- |
||||
## Open |
||||
|
||||
## Open Issues |
||||
### ISS-001: _sogo_static_view auto-sync |
||||
|
||||
### ISS-001: _sogo_static_view tidak auto-sync setelah edit password |
||||
### ISS-008: Cross-domain gisportal.id ↔ geonet.co.id (2026-07-06) |
||||
|
||||
| Field | Value | |
||||
|-------|-------| |
||||
| Status | Open | |
||||
| Severity | Medium | |
||||
| Found | 2026-07-03 | |
||||
- `admin@gisportal.id` → user cPanel-only `@geonet.co.id`: cPanel reject (From vs SMTP auth) |
||||
- `rianjawa93@geonet.co.id` tidak ada di Mailcow |
||||
- Doc: [notes/gisportal-id-mail.md](./notes/gisportal-id-mail.md) |
||||
|
||||
**Workaround:** UPDATE _sogo_static_view FROM mailbox.password; restart sogo container. |
||||
## Resolved |
||||
|
||||
--- |
||||
|
||||
## Resolved Issues |
||||
|
||||
### ISS-003: SOGo Unauthorized — authsource mailcow + sync view (2026-07-03) |
||||
### ISS-004: Gmail 550 — relay sc138:587 (2026-07-03) |
||||
### ISS-005: fetchmailrc parse — ssl after user, no sslcertck (2026-07-03) |
||||
- ISS-006 Internal mail cPanel user — transport Jalur B `rbsetiawan@` (2026-07-06) |
||||
- ISS-003 SOGo Unauthorized (2026-07-03) |
||||
- ISS-004 Gmail 550 relay (2026-07-03) |
||||
- ISS-005 fetchmail SSL (2026-07-03) |
||||
- ISS-007 Outlook SMTP cert (2026-07-06) |
||||
@ -0,0 +1,130 @@
@@ -0,0 +1,130 @@
|
||||
# gisportal.id — Multi-Domain Mail (Mailcow murni) |
||||
|
||||
> **Penting:** `gisportal.id` **tidak punya cPanel**. Domain ini langsung publik → `117.102.73.102` → port email di-forward ke Mailcow (`10.100.1.28`). |
||||
> |
||||
> Berbeda dengan `geonet.co.id` yang masih **hybrid** (MX/inbox banyak user di cPanel). |
||||
|
||||
--- |
||||
|
||||
## Arsitektur dua domain di satu Mailcow |
||||
|
||||
``` |
||||
┌─────────────────────────────────────┐ |
||||
│ Mailcow sync.geonet.co.id (.28) │ |
||||
│ IP publik: 117.102.73.102 │ |
||||
└─────────────────────────────────────┘ |
||||
▲ ▲ |
||||
MX mail.gisportal.id MX geonet.co.id (masih cPanel) |
||||
(langsung ke .102) + fetchmail / transport map |
||||
│ │ |
||||
gisportal.id │ │ geonet.co.id |
||||
(NO cPanel) │ │ (hybrid cPanel) |
||||
│ │ |
||||
admin@gisportal.id support@, rbsetiawan@, … |
||||
``` |
||||
|
||||
| Domain | Hosting email | Inbound | Outbound | |
||||
|--------|---------------|---------|----------| |
||||
| **gisportal.id** | **Mailcow saja** | MX → `.102` → Mailcow | Langsung dari Mailcow (tanpa relay cPanel) | |
||||
| **geonet.co.id** | Hybrid | MX masih cPanel + fetchmail / transport | Relay cPanel `:587` (transisi) | |
||||
|
||||
Di Mailcow Admin, domain `gisportal.id` harus **`relayhost` = none** (bukan relay cPanel seperti `geonet.co.id`). |
||||
|
||||
--- |
||||
|
||||
## DNS `gisportal.id` — wajib disesuaikan |
||||
|
||||
SPF saat ini masih mencantumkan **IP cPanel lama** — itu salah untuk domain tanpa cPanel. |
||||
|
||||
| Record | Target | Status | |
||||
|--------|--------|--------| |
||||
| MX | `10 mail.gisportal.id` | ✅ | |
||||
| A `mail.gisportal.id` | `117.102.73.102` | ✅ | |
||||
| A `gisportal.id` | `117.102.73.102` (web) | ✅ | |
||||
| **SPF** | `v=spf1 ip4:117.102.73.102 -all` | ✅ 2026-07-06 (TTL 1800, propagasi ~30 menit) | |
||||
| **DKIM** | TXT dari Mailcow Admin | ⏳ publish | |
||||
| PTR | `117.102.73.102` → `sync.geonet.co.id` | shared dengan geonet | |
||||
|
||||
**SPF yang benar** (tanpa cPanel): |
||||
|
||||
```txt |
||||
v=spf1 ip4:117.102.73.102 -all |
||||
``` |
||||
|
||||
**Hapus** entri lama seperti `ip4:103.229.73.23` dan `include:idse.idcloudhosting.com` dari SPF `gisportal.id` — itu sisa hosting lama, bukan Mailcow. |
||||
|
||||
DKIM: Mailcow Admin → Configuration → Configuration & Details → **ARC/DKIM keys** → domain `gisportal.id` → publish TXT ke DNS. |
||||
|
||||
--- |
||||
|
||||
## Perilaku `admin@gisportal.id` |
||||
|
||||
### Yang sudah OK di server |
||||
|
||||
| Arah | Contoh | Mekanisme | |
||||
|------|--------|-----------| |
||||
| Terima internal Mailcow | `support@` → `admin@gisportal.id` | LMTP lokal ✅ | |
||||
| Kirim ke internet | `admin@gisportal.id` → Gmail | SMTP langsung Mailcow ✅ | |
||||
| Kirim ke diri sendiri | SOGo self-test | ✅ | |
||||
|
||||
### Masalah yang tersisa (bukan karena gisportal punya cPanel) |
||||
|
||||
| Gejala | Penyebab sebenarnya | |
||||
|--------|---------------------| |
||||
| Kirim ke `rbsetiawan@geonet.co.id` gagal | **Penerima** di cPanel (`geonet.co.id` hybrid). Transport map pakai auth `support@geonet.co.id` → cPanel menolak From `@gisportal.id` | |
||||
| Kirim ke `rianjawa93@geonet.co.id` gagal | Mailbox tidak ada di Mailcow; tidak ada transport map | |
||||
| Kirim ke `support@` saja OK | `support@` punya mailbox aktif di Mailcow | |
||||
| Terima dari `rbsetiawan@` sempat ditolak | Email dari **cPanel geonet** lewat spam filter; Rspamd `SPOOFED_UNAUTH` — forwarding hosts sudah ditambahkan | |
||||
| Terima dari luar lambat/gagal | Tunggu propagasi SPF baru; pastikan DKIM sudah publish | |
||||
|
||||
**Kirim ke user `@geonet.co.id` yang masih di cPanel** dari akun `@gisportal.id` memang bermasalah — ini konflik **cross-domain ke hybrid geonet**, bukan masalah hosting gisportal. |
||||
|
||||
**Solusi kirim ke user cPanel-only `@geonet.co.id`:** |
||||
|
||||
| Opsi | Keterangan | |
||||
|------|------------| |
||||
| A | Kirim dari `support@geonet.co.id` (bukan `@gisportal.id`) | |
||||
| B | Tambah transport map + kredensial SMTP yang domain-nya cocok (jarang praktis) | |
||||
| C | Migrasi penerima ke Mailcow (LDAP / mailbox) | |
||||
|
||||
--- |
||||
|
||||
## Inbound ke `@gisportal.id` — alur yang benar |
||||
|
||||
``` |
||||
Pengirim (Gmail / rbsetiawan@cPanel / dll) |
||||
→ DNS MX gisportal.id = mail.gisportal.id |
||||
→ 117.102.73.102:25 (forward ke Mailcow) |
||||
→ Postfix Mailcow → inbox admin@gisportal.id |
||||
``` |
||||
|
||||
Tidak ada hop cPanel untuk domain `gisportal.id`. |
||||
|
||||
Jika `rbsetiawan@` kirim dari **webmail cPanel geonet**, pastikan penerima `admin@gisportal.id` — MX lookup harus ke `mail.gisportal.id`, bukan lewat relay internal geonet saja. |
||||
|
||||
--- |
||||
|
||||
## Checklist |
||||
|
||||
- [ ] SPF `gisportal.id` → `v=spf1 ip4:117.102.73.102 -all` (hapus IP cPanel lama) |
||||
- [ ] DKIM publish dari Mailcow |
||||
- [ ] Verifikasi domain `gisportal.id` di Mailcow: **relayhost = none** |
||||
- [ ] Tes terima dari Gmail → `admin@gisportal.id` |
||||
- [ ] Tes terima dari `support@geonet.co.id` → refresh Inbox SOGo |
||||
- [ ] (Opsional) DMARC `_dmarc.gisportal.id` |
||||
|
||||
--- |
||||
|
||||
## Script terkait |
||||
|
||||
| Script | Fungsi | |
||||
|--------|--------| |
||||
| `scripts/fix-sogo-domain.sh` | Sync password SOGo setelah buat mailbox | |
||||
| `scripts/setup-gisportal-inbound-whitelist.sh` | Whitelist NAT/cPanel forwarder untuk inbound | |
||||
|
||||
--- |
||||
|
||||
## Referensi |
||||
|
||||
- [hybrid-migration-cpanel-mailcow.md](./hybrid-migration-cpanel-mailcow.md) — hanya untuk **geonet.co.id** |
||||
- [ldap-ad-mailcow.md](./ldap-ad-mailcow.md) — AD domain `gisportal.id` vs mailbox `@geonet.co.id` / `@gisportal.id` |
||||
@ -0,0 +1,128 @@
@@ -0,0 +1,128 @@
|
||||
# Hybrid Migration — User @geonet.co.id (cPanel vs Mailcow) |
||||
|
||||
> **Kapan baca:** User masih baca email di cPanel, tapi sudah masuk grup `Mail-Users` / punya mailbox Mailcow. |
||||
|
||||
--- |
||||
|
||||
## Masalah |
||||
|
||||
``` |
||||
support@ (Mailcow) --kirim--> rbsetiawan@geonet.co.id |
||||
| |
||||
Postfix Mailcow: LOCAL delivery |
||||
(karena mailbox ada di Mailcow) |
||||
| |
||||
inbox Mailcow saja |
||||
X |
||||
inbox cPanel (MX eksternal) |
||||
``` |
||||
|
||||
| Arah email | rbsetiawan baca di | Masuk ke | |
||||
|------------|-------------------|----------| |
||||
| Internet → MX cPanel | cPanel | ✅ cPanel | |
||||
| support@ → rbsetiawan@ (internal Mailcow) | cPanel | ❌ hanya Mailcow | |
||||
|
||||
**Satu alamat email = satu inbox canonical.** Tidak bisa mailbox aktif di Mailcow **dan** inbox utama di cPanel untuk routing internal. |
||||
|
||||
--- |
||||
|
||||
## Dua jalur per user |
||||
|
||||
### Jalur A — Migrasi penuh ke Mailcow (disarankan jangka panjang) |
||||
|
||||
Sesuai [`email-sync-migration-concept.md`](./email-sync-migration-concept.md). |
||||
|
||||
| Step | Aksi | |
||||
|------|------| |
||||
| 1 | Tetap di grup `Mail-Users` | |
||||
| 2 | Mailbox Mailcow aktif (LDAP) | |
||||
| 3 | Tambah **fetchmail POP3** dari cPanel → Mailcow (seperti `support@`) | |
||||
| 4 | User ganti Outlook → IMAP `sync.geonet.co.id` + password AD | |
||||
| 5 | Inbox canonical = **Mailcow saja** | |
||||
|
||||
Email internal dari `support@` sudah masuk Mailcow — user tinggal baca di sana. |
||||
|
||||
### Jalur B — Tetap di cPanel (belum migrasi) |
||||
|
||||
| Step | Aksi | |
||||
|------|------| |
||||
| 1 | **Keluarkan** user dari grup AD `Mail-Users` | |
||||
| 2 | Nonaktifkan mailbox di Mailcow Admin (**Inactive**) | |
||||
| 3 | LDAP sync: `docker exec mailcowdockerized-php-fpm-mailcow-1 php /crons/ldap-sync.php` | |
||||
| 4 | **Transport map** → relay ke SMTP cPanel (wajib) | |
||||
| 5 | Aktifkan alias (jika ada) agar SOGo terima penerima | |
||||
| 6 | User tetap baca email di cPanel | |
||||
|
||||
Tanpa transport map: kirim internal dari Mailcow ke user tanpa mailbox → error `User unknown`. |
||||
|
||||
#### Transport map (Mailcow Admin UI) |
||||
|
||||
**Configuration → Routing → Transport maps → Add** |
||||
|
||||
| Field | Contoh `rbsetiawan@` | |
||||
|-------|----------------------| |
||||
| Destination | `rbsetiawan@geonet.co.id` | |
||||
| Nexthop | `[sc138.idcloudhosting.cloud]:587` | |
||||
| Username | `support@geonet.co.id` (sama relay outbound) | |
||||
| Password | password SMTP cPanel relay | |
||||
| Active | ✅ | |
||||
|
||||
Atau jalankan script: `scripts/setup-transport-cpanel-user.sh rbsetiawan@geonet.co.id` |
||||
|
||||
**Catatan:** Port **25** ke cPanel ditolak RBL (IP publik Mailcow). Pakai **587 + auth**. |
||||
|
||||
Verifikasi Postfix: `postmap -q rbsetiawan@geonet.co.id mysql:/opt/postfix/conf/sql/mysql_transport_maps.cf` → harus return `smtp_via_transport_maps:[sc138...]:587` |
||||
|
||||
--- |
||||
|
||||
## Kebijakan tim (rekomendasi) |
||||
|
||||
| Fase user | Grup `Mail-Users` | Mailbox Mailcow | Baca email via | |
||||
|-----------|-------------------|-----------------|----------------| |
||||
| **Belum migrasi** | ❌ Jangan tambah dulu | ❌ | cPanel | |
||||
| **Migrasi** | ✅ | ✅ | `sync.geonet.co.id` IMAP | |
||||
| **support@** | ✅ | ✅ + fetchmail POP3 | Mailcow | |
||||
|
||||
**Jangan** masukkan semua user ke `Mail-Users` sekaligus jika masih pakai cPanel harian. |
||||
|
||||
--- |
||||
|
||||
## Untuk kasus rbsetiawan@ saat ini (Jalur B — diterapkan 2026-07-06) |
||||
|
||||
| Item | Status | |
||||
|------|--------| |
||||
| Keluar grup `Mail-Users` | ✅ | |
||||
| Mailbox Mailcow Inactive | ✅ (`active=0`) | |
||||
| LDAP sync | ✅ | |
||||
| Transport map → cPanel :587 | ✅ | |
||||
| Alias aktif (SOGo RCPT) | ✅ | |
||||
| Tes kirim support@ → rbsetiawan@ | ✅ verified — inbox cPanel | |
||||
|
||||
Email lama yang sudah masuk inbox Mailcow **tidak otomatis pindah** ke cPanel. |
||||
|
||||
Untuk migrasi penuh (Jalur A): fetchmail POP3 + Outlook IMAP Mailcow — lihat [`email-sync-migration-concept.md`](./email-sync-migration-concept.md). |
||||
|
||||
--- |
||||
|
||||
## fetchmail multi-user |
||||
|
||||
Contoh tambahan di `/opt/fetchmail/fetchmailrc` (satu entry per user migrasi): |
||||
|
||||
``` |
||||
poll mail.geonet.co.id with proto POP3 port 995 |
||||
user "rbsetiawan@geonet.co.id" there with password "..." is "rbsetiawan@geonet.co.id" here |
||||
ssl |
||||
no sslcertck |
||||
smtphost 127.0.0.1 |
||||
smtpname sync.geonet.co.id |
||||
fetchall |
||||
nokeep |
||||
``` |
||||
|
||||
--- |
||||
|
||||
## Referensi |
||||
|
||||
- [email-sync-migration-concept.md](./email-sync-migration-concept.md) |
||||
- [ldap-ad-mailcow.md](./ldap-ad-mailcow.md) |
||||
- [issues.md](../issues.md) ISS-006 |
||||
@ -0,0 +1,101 @@
@@ -0,0 +1,101 @@
|
||||
# System Requirements — Mailcow |
||||
|
||||
**Owner:** runtime minimum agar Mailcow + fetchmail berjalan. |
||||
Inventori host: [server.md](./server.md). Env: [.env.example](../.env.example). |
||||
|
||||
--- |
||||
|
||||
## Ringkasan |
||||
|
||||
| Field | Value | |
||||
|-------|-------| |
||||
| Project | `Mailcow/` | |
||||
| Tipe | infra (mail server) | |
||||
| Last updated | 2026-07-06 | |
||||
|
||||
--- |
||||
|
||||
## Platform & OS |
||||
|
||||
| Komponen | Minimum | Dipakai saat ini | |
||||
|----------|---------|------------------| |
||||
| OS server | Ubuntu 22.04 LTS | Ubuntu 22.04.5 LTS | |
||||
| Arsitektur | x64 | x64 | |
||||
| `vm.max_map_count` | 262144 | 262144 | |
||||
|
||||
--- |
||||
|
||||
## Runtime & Toolchain |
||||
|
||||
| Tool | Minimum | Dipakai | Cek | |
||||
|------|---------|---------|-----| |
||||
| Docker | 24+ | 29.x | `docker --version` | |
||||
| Docker Compose | v2 | v5 | `docker compose version` | |
||||
| fetchmail | 6.x | systemd package | `fetchmail -V` | |
||||
| systemd | — | timer 2 menit | `systemctl status fetchmail-support.timer` | |
||||
|
||||
--- |
||||
|
||||
## Resource minimum (VM Mailcow) |
||||
|
||||
| Lingkungan | CPU | RAM | Disk | |
||||
|------------|-----|-----|------| |
||||
| prod (30+ user) | 8 vCPU | 16 GiB | 2×256 GiB SSD | |
||||
| prod (saat ini) | **16 vCPU** | **32 GiB** | 2×512 GiB SSD | |
||||
|
||||
Disk 2: `/data/mailcow/vmail` (Dovecot mail storage live). |
||||
|
||||
--- |
||||
|
||||
## Dependency eksternal |
||||
|
||||
| Dependency | Host | Dipakai untuk | |
||||
|------------|------|---------------| |
||||
| nginx reverse proxy | `10.100.1.24` | HTTPS UI `sync.geonet.co.id` | |
||||
| Active Directory LDAP | `10.100.1.40:389` | Identity Provider (bukan `support@`) | |
||||
| cPanel POP3 | `mail.geonet.co.id:995` | fetchmail drain (transisi) | |
||||
| cPanel SMTP relay | `sc138.idcloudhosting.cloud:587` | Outbound transisi | |
||||
| QNAP NAS | `10.100.1.10` | Backup harian | |
||||
| Dockge primary | `10.100.1.24` | Manajemen stack | |
||||
|
||||
--- |
||||
|
||||
## Variabel URL & konfigurasi (no hardcode) |
||||
|
||||
| Variabel | Wajib | Contoh | Dipakai oleh | |
||||
|----------|-------|--------|--------------| |
||||
| `MAILCOW_HOSTNAME` | ya | `sync.geonet.co.id` | Mailcow generate_config | |
||||
| `MAILCOW_VM_IP` | ya | `10.100.1.28` | docs, SSH | |
||||
| `MAILCOW_SUPPORT_EMAIL` | ya | `support@geonet.co.id` | fetchmail, Zammad | |
||||
| `MAILCOW_SUPPORT_PASSWORD` | ya | *(secret)* | fetchmail, SOGo, SMTP | |
||||
| `LDAP_HOST` | opsional | `10.100.1.40` | Identity Provider | |
||||
| `LEGACY_SMTP_HOST` | transisi | `sc138.idcloudhosting.cloud` | relay outbound | |
||||
|
||||
Detail: [environment.md](./environment.md), [.env.example](../.env.example). |
||||
|
||||
--- |
||||
|
||||
## Port & protokol |
||||
|
||||
| Service | Port | Protokol | |
||||
|---------|------|----------| |
||||
| SMTP inbound | 25 | TCP | |
||||
| SMTPS | 465 | TCP/TLS | |
||||
| Submission | 587 | TCP/STARTTLS | |
||||
| IMAPS | 993 | TCP/TLS | |
||||
| POP3S | 995 | TCP/TLS | |
||||
| HTTPS (UI) | 443 | HTTPS | |
||||
| Dockge agent | 5001 | HTTP (LAN only) | |
||||
|
||||
--- |
||||
|
||||
## Client IMAP (PC user) |
||||
|
||||
| Setting | Nilai | |
||||
|---------|-------| |
||||
| Server | `sync.geonet.co.id` | |
||||
| Port | 993 SSL/TLS | |
||||
| Username | `support@geonet.co.id` | |
||||
| Password | Password Mailcow (bukan AD) | |
||||
|
||||
Panduan lengkap: [guide/outlook-imap-setup.md](./guide/outlook-imap-setup.md). |
||||
@ -1,47 +1,39 @@
@@ -1,47 +1,39 @@
|
||||
# TODO — Mailcow |
||||
|
||||
> Last updated: 2026-07-03 |
||||
> Last updated: 2026-07-06 |
||||
|
||||
--- |
||||
|
||||
## High Priority |
||||
|
||||
- [ ] Publish DKIM TXT dkim._domainkey.geonet.co.id (key dari Mailcow API) |
||||
- [ ] Update SPF geonet.co.id — include IP 117.102.73.102 atau relay sementara |
||||
- [ ] Zammad channel email → IMAP/SMTP Mailcow 10.100.1.28 (ganti cPanel) |
||||
- [ ] **DKIM `gisportal.id`** publish TXT dari Mailcow Admin → Master Web |
||||
- [ ] Verifikasi terima/kirim `admin@gisportal.id` (Gmail ↔ SOGo) setelah DKIM |
||||
- [ ] Publish DKIM + SPF `geonet.co.id` |
||||
- [ ] Zammad channel email → IMAP/SMTP Mailcow `10.100.1.28` |
||||
|
||||
--- |
||||
|
||||
## Medium Priority |
||||
|
||||
- [ ] PTR/rDNS 117.102.73.102 → sync.geonet.co.id |
||||
- [ ] Buat scripts/install-relay-cpanel.sh (mirror fetchmail installer) |
||||
- [ ] Automasi sync _sogo_static_view setelah password mailbox mailcow berubah |
||||
- [ ] Monitoring fetchmail (Uptime Kuma atau alert log) |
||||
- [ ] PTR/rDNS `117.102.73.102` → `sync.geonet.co.id` |
||||
- [ ] Script `install-relay-cpanel.sh` |
||||
- [ ] Auto-sync `_sogo_static_view` setelah ganti password |
||||
- [ ] Hapus relayhost id=2 typo di Mailcow Admin (jika masih ada) |
||||
|
||||
--- |
||||
|
||||
## Low Priority |
||||
|
||||
- [ ] fetchmail entry untuk mailbox tambahan (info@, dll.) |
||||
- [ ] LDAP user lain di Mail-Users — provisioning + Outlook guide |
||||
- [ ] Domain sekunder gegeo.my.id |
||||
- [ ] MX cutover ke sync.geonet.co.id (setelah 2–4 minggu stabil) |
||||
- [ ] Matikan fetchmail + relay cPanel pasca cutover |
||||
- [ ] MX cutover `geonet.co.id` → `sync.geonet.co.id` |
||||
- [ ] Matikan fetchmail + relay cPanel setelah cutover |
||||
- [ ] Transport map `rianjawa93@` jika tetap di cPanel |
||||
|
||||
--- |
||||
|
||||
## Selesai (Sesi 2026-07-03) |
||||
## Selesai (Sesi Ini) |
||||
|
||||
- [x] fetchmail POP3 drain support@ + timer 2 menit |
||||
- [x] Relay outbound cPanel :587 untuk geonet.co.id |
||||
- [x] SOGo login + kirim/terima email verified |
||||
- [x] scripts/install-fetchmail-support.sh |
||||
- [x] Dokumentasi handover sesi |
||||
|
||||
--- |
||||
|
||||
## Technical Debt |
||||
|
||||
- [ ] support@ service account vs LDAP — dokumentasikan keputusan |
||||
- [ ] context-index diagram IP — align ke .28 |
||||
- [x] Jalur B `rbsetiawan@`: transport map + verified `support@` → cPanel |
||||
- [x] Domain `gisportal.id` + mailbox `admin@gisportal.id` + SOGo |
||||
- [x] Forwarding hosts whitelist inbound gisportal |
||||
- [x] SPF `gisportal.id`: `v=spf1 ip4:117.102.73.102 -all` (Master Web, propagasi OK) |
||||
- [x] Scripts + docs dual-domain (`gisportal-id-mail.md`, hybrid migration) |
||||
|
||||
@ -0,0 +1,89 @@
@@ -0,0 +1,89 @@
|
||||
# Version History |
||||
|
||||
**Owner:** riwayat versi deploy/config Mailcow — append per perubahan material. |
||||
Sinkron dengan [changelog.md](./changelog.md). |
||||
|
||||
**Wajib sebelum deploy:** append entri baru di sini (bullet poin jelas). |
||||
|
||||
--- |
||||
|
||||
## [1.2.5] - 2026-07-06 |
||||
|
||||
- SPF `gisportal.id` dipublish di Master Web: `v=spf1 ip4:117.102.73.102 -all` |
||||
|
||||
--- |
||||
|
||||
## [1.2.4] - 2026-07-06 |
||||
|
||||
- Dokumentasi `gisportal.id`: domain **Mailcow murni** (tanpa cPanel), langsung `.102` → Mailcow |
||||
- SPF `gisportal.id` harus diganti: `v=spf1 ip4:117.102.73.102 -all` (hapus IP cPanel lama) |
||||
- Whitelist forwarding hosts untuk inbound dari pengirim cPanel geonet |
||||
- Cross-domain `@gisportal.id` → user cPanel-only `@geonet.co.id` tetap terbatas (bukan masalah cPanel gisportal) |
||||
|
||||
--- |
||||
|
||||
## [1.2.3] - 2026-07-06 |
||||
|
||||
- **Jalur B hybrid** `rbsetiawan@geonet.co.id`: keluar `Mail-Users`, mailbox Inactive, transport map ke cPanel |
||||
- Transport: `rbsetiawan@geonet.co.id` → `[sc138.idcloudhosting.cloud]:587` (auth `support@`) |
||||
- Alias `rbsetiawan@` diaktifkan agar SOGo terima penerima |
||||
- Script: `scripts/setup-transport-cpanel-user.sh` |
||||
- Port 25 ke cPanel ditolak RBL; wajib relay :587 |
||||
- **Verified:** kirim `support@` (Mailcow/LDAP) → `rbsetiawan@` (cPanel) OK |
||||
|
||||
--- |
||||
|
||||
## [1.2.2] - 2026-07-06 |
||||
|
||||
- Semua user `@geonet.co.id` ditambahkan ke grup AD **Mail-Users** |
||||
- LDAP sync: **26 mailbox** aktif (`authsource=ldap`) |
||||
- Kirim internal `support@` → `rbsetiawan@` verified (SOGo/webmail) |
||||
- Kirim eksternal → Gmail verified |
||||
|
||||
--- |
||||
|
||||
## [1.2.1] - 2026-07-06 |
||||
|
||||
- Fix Outlook SMTP: pasang cert **Let's Encrypt** ke Postfix/Dovecot (salin dari nginx `.24`) |
||||
- Script: `scripts/sync-ssl-from-nginx.sh` |
||||
- Penyebab error: port 587 pakai cert self-signed + Outlook port 587 harus STARTTLS |
||||
|
||||
--- |
||||
|
||||
## [1.2.0] - 2026-07-06 |
||||
|
||||
- `support@geonet.co.id` authsource **mailcow → ldap** (satu mailbox, inbox tidak dipindah) |
||||
- User IMAP/SMTP: password **Active Directory** (`Mail-Users`) |
||||
- fetchmail POP3 drain **tetap aktif** — inbound SSOT hosting → inbox Mailcow sama |
||||
- Script: `scripts/switch-support-to-ldap.sh` |
||||
- ADR: `docs/adr/ADR-0001-support-ldap-auth.md` |
||||
- Inbox verified: 11 pesan setelah switch |
||||
|
||||
--- |
||||
|
||||
## [1.1.0] - 2026-07-06 |
||||
|
||||
- Bootstrap dokumentasi AI-Agent-Standards (AGENTS.md, version.md, system-requirements.md, guide/) |
||||
- Panduan IMAP/SMTP Outlook user → `docs/guide/outlook-imap-setup.md` |
||||
- Verifikasi fetchmail POP3 drain aktif (timer 2 menit, inbox Mailcow 9 pesan) |
||||
- Perbaikan encoding `changelog.md` / `todo.md` (UTF-8) |
||||
|
||||
--- |
||||
|
||||
## [1.0.0] - 2026-07-03 |
||||
|
||||
- Mailcow stack live di VM `10.100.1.28` (`/opt/stacks/mailcow`) |
||||
- Domain `geonet.co.id` + mailbox `support@geonet.co.id` (authsource mailcow) |
||||
- fetchmail POP3 drain cPanel → Mailcow (`scripts/install-fetchmail-support.sh`, timer 2 menit) |
||||
- Outbound relay cPanel `sc138.idcloudhosting.cloud:587` (transisi, Gmail tidak reject) |
||||
- SOGo login + kirim/terima verified |
||||
- LDAP Identity Provider untuk user AD (`Mail-Users`) |
||||
- Nginx proxy `sync.geonet.co.id` di `10.100.1.24` + Let's Encrypt |
||||
- Dockge agent port `5001` di VM Mailcow |
||||
|
||||
--- |
||||
|
||||
## [0.1.0] - 2026-07-01 |
||||
|
||||
- Inisialisasi dokumentasi repo Mailcow |
||||
- Konsep POP3 drain + LDAP AD (`docs/notes/`) |
||||
@ -0,0 +1,37 @@
@@ -0,0 +1,37 @@
|
||||
#!/bin/bash |
||||
# Fix SOGo for mailcow-auth mailboxes (authsource=mailcow), especially new domains. |
||||
# Run after: new domain/mailbox, password change in Admin UI, or SOGo Unauthorized. |
||||
# Usage: fix-sogo-domain.sh [user@domain.tld] |
||||
set -euo pipefail |
||||
STACK='/opt/stacks/mailcow' |
||||
USER="${1:-admin@gisportal.id}" |
||||
|
||||
echo "== Sync c_password from mailbox (authsource=mailcow) ==" |
||||
docker exec mailcowdockerized-mysql-mailcow-1 bash -lc ' |
||||
mysql mailcow -uroot -p"$MYSQL_ROOT_PASSWORD" -e " |
||||
UPDATE _sogo_static_view s |
||||
INNER JOIN mailbox m ON m.username = s.c_name |
||||
SET s.c_password = m.password |
||||
WHERE m.authsource = \"mailcow\" AND m.active IN (\"1\",\"2\"); |
||||
" |
||||
' |
||||
|
||||
echo "== Verify: $USER ==" |
||||
docker exec mailcowdockerized-mysql-mailcow-1 bash -lc " |
||||
mysql mailcow -uroot -p\"\$MYSQL_ROOT_PASSWORD\" -N -e \" |
||||
SELECT 'mailbox', LEFT(password,55) FROM mailbox WHERE username='${USER}'; |
||||
SELECT 'sogo', LEFT(c_password,55) FROM _sogo_static_view WHERE c_name='${USER}'; |
||||
\" |
||||
" |
||||
|
||||
echo "== Restart SOGo ==" |
||||
cd "$STACK" |
||||
docker compose restart sogo-mailcow |
||||
sleep 8 |
||||
|
||||
echo "== SOGo domains ==" |
||||
docker exec mailcowdockerized-sogo-mailcow-1 grep -E '<key>(geonet|gisportal|gegeo)' /var/lib/sogo/GNUstep/Defaults/sogod.plist || \ |
||||
docker exec mailcowdockerized-sogo-mailcow-1 grep '<key>.*\.id</key>' /var/lib/sogo/GNUstep/Defaults/sogod.plist |
||||
|
||||
echo "" |
||||
echo "DONE. Login SOGo with Mailcow mailbox password (NOT AD password for authsource=mailcow)." |
||||
@ -0,0 +1,19 @@
@@ -0,0 +1,19 @@
|
||||
#!/bin/bash |
||||
# Fix inbound mail to @gisportal.id from cPanel/NAT path (rspamd SPOOFED_UNAUTH) |
||||
set -euo pipefail |
||||
|
||||
echo "== Add forwarding hosts (trusted inbound relays) ==" |
||||
docker exec mailcowdockerized-mysql-mailcow-1 bash -lc ' |
||||
mysql mailcow -uroot -p"$MYSQL_ROOT_PASSWORD" -e " |
||||
INSERT IGNORE INTO forwarding_hosts (host, source, filter_spam) VALUES |
||||
(\"10.100.1.1\", \"NAT gateway inbound\", 1), |
||||
(\"103.229.73.23\", \"cPanel sc138\", 1), |
||||
(\"sc138.idcloudhosting.cloud\", \"cPanel SMTP hostname\", 1), |
||||
(\"spfilter-2.idcloudhosting.com\", \"cPanel spam filter\", 1); |
||||
SELECT host, source FROM forwarding_hosts; |
||||
" |
||||
' |
||||
|
||||
docker exec mailcowdockerized-postfix-mailcow-1 postfix reload |
||||
docker exec mailcowdockerized-rspamd-mailcow-1 rspamadm reload 2>/dev/null || true |
||||
echo "DONE forwarding hosts" |
||||
@ -0,0 +1,79 @@
@@ -0,0 +1,79 @@
|
||||
#!/bin/bash |
||||
# Path B hybrid: relay internal mail for a cPanel-only user via transport map. |
||||
# Prerequisite: user removed from AD Mail-Users, mailbox inactive in Mailcow Admin. |
||||
# Usage: setup-transport-cpanel-user.sh user@geonet.co.id |
||||
set -euo pipefail |
||||
|
||||
EMAIL="${1:-}" |
||||
NEXTHOP="${TRANSPORT_NEXTHOP:-[sc138.idcloudhosting.cloud]:587}" |
||||
RELAYHOST_ID="${TRANSPORT_RELAYHOST_ID:-1}" |
||||
|
||||
STACK='/opt/stacks/mailcow' |
||||
MYSQL_C='mailcowdockerized-mysql-mailcow-1' |
||||
POSTFIX_C='mailcowdockerized-postfix-mailcow-1' |
||||
PHP_C='mailcowdockerized-php-fpm-mailcow-1' |
||||
|
||||
if [ -z "$EMAIL" ]; then |
||||
echo "Usage: $0 user@geonet.co.id" |
||||
exit 1 |
||||
fi |
||||
|
||||
mysql_q() { |
||||
docker exec "$MYSQL_C" bash -lc "mysql mailcow -uroot -p\"\$MYSQL_ROOT_PASSWORD\" -N -e \"$1\"" |
||||
} |
||||
|
||||
mysql_exec() { |
||||
docker exec "$MYSQL_C" bash -lc "mysql mailcow -uroot -p\"\$MYSQL_ROOT_PASSWORD\" -e \"$1\"" |
||||
} |
||||
|
||||
echo "== LDAP sync ==" |
||||
docker exec "$PHP_C" php /crons/ldap-sync.php || true |
||||
|
||||
echo "== Mailbox check (expect active=0) ==" |
||||
MB=$(mysql_q "SELECT username, active, authsource FROM mailbox WHERE username='${EMAIL}';") |
||||
echo "$MB" |
||||
if echo "$MB" | grep -qP '\t1\t'; then |
||||
echo "WARN: mailbox still active — deactivate in Mailcow Admin first (Path B)" |
||||
fi |
||||
|
||||
echo "== Transport map ==" |
||||
CNT=$(mysql_q "SELECT COUNT(*) FROM transports WHERE destination='${EMAIL}';") |
||||
if [ "${CNT}" = "0" ]; then |
||||
mysql_exec " |
||||
INSERT INTO transports (destination, nexthop, username, password, is_mx_based, active) |
||||
SELECT '${EMAIL}', '${NEXTHOP}', r.username, r.password, 0, 1 |
||||
FROM relayhosts r |
||||
WHERE r.id=${RELAYHOST_ID} AND r.active=1 |
||||
LIMIT 1; |
||||
" |
||||
echo "Inserted transport for ${EMAIL} -> ${NEXTHOP}" |
||||
else |
||||
mysql_exec " |
||||
UPDATE transports t |
||||
JOIN relayhosts r ON r.id=${RELAYHOST_ID} AND r.active=1 |
||||
SET t.nexthop='${NEXTHOP}', t.username=r.username, t.password=r.password, t.active=1 |
||||
WHERE t.destination='${EMAIL}'; |
||||
" |
||||
echo "Updated existing transport for ${EMAIL}" |
||||
fi |
||||
|
||||
mysql_exec "SELECT id, destination, nexthop, username, is_mx_based, active FROM transports WHERE destination='${EMAIL}';" |
||||
|
||||
echo "== Alias (SOGo RCPT acceptance) ==" |
||||
ALIAS=$(mysql_q "SELECT COUNT(*) FROM alias WHERE address='${EMAIL}';") |
||||
if [ "${ALIAS}" != "0" ]; then |
||||
mysql_exec "UPDATE alias SET active=1 WHERE address='${EMAIL}';" |
||||
mysql_exec "SELECT address, goto, active FROM alias WHERE address='${EMAIL}';" |
||||
else |
||||
echo "No alias row for ${EMAIL} (OK if sending only via postfix, not SOGo)" |
||||
fi |
||||
|
||||
echo "== Postfix lookup ==" |
||||
docker exec "$POSTFIX_C" postmap -q "${EMAIL}" mysql:/opt/postfix/conf/sql/mysql_transport_maps.cf || true |
||||
|
||||
echo "== Reload postfix ==" |
||||
docker exec "$POSTFIX_C" postfix reload |
||||
|
||||
echo "" |
||||
echo "DONE. Test: send from support@ to ${EMAIL}, verify inbox on cPanel." |
||||
echo "Admin UI: Configuration -> Routing -> Transport maps" |
||||
@ -0,0 +1,49 @@
@@ -0,0 +1,49 @@
|
||||
#!/bin/bash |
||||
# Switch support@geonet.co.id from authsource mailcow → ldap |
||||
# Inbox/fetchmail unchanged — only IMAP/SMTP login uses AD password |
||||
set -euo pipefail |
||||
|
||||
MAILBOX='support@geonet.co.id' |
||||
STACK='/opt/stacks/mailcow' |
||||
MYSQL_C='mailcowdockerized-mysql-mailcow-1' |
||||
DOVECOT_C='mailcowdockerized-dovecot-mailcow-1' |
||||
SOGO_C='mailcowdockerized-sogo-mailcow-1' |
||||
PHP_C='mailcowdockerized-php-fpm-mailcow-1' |
||||
|
||||
mysql_q() { |
||||
docker exec "$MYSQL_C" bash -lc "mysql mailcow -uroot -p\"\$MYSQL_ROOT_PASSWORD\" -N -e \"$1\"" |
||||
} |
||||
|
||||
echo "== Pre-check ==" |
||||
BEFORE=$(mysql_q "SELECT username, active, authsource FROM mailbox WHERE username='${MAILBOX}';") |
||||
echo "Mailbox: $BEFORE" |
||||
if ! echo "$BEFORE" | grep -q "$MAILBOX"; then |
||||
echo "ERROR: mailbox ${MAILBOX} not found" |
||||
exit 1 |
||||
fi |
||||
|
||||
echo "== LDAP sync (import/provision) ==" |
||||
docker exec "$PHP_C" php /crons/ldap-sync.php || true |
||||
|
||||
echo "== Switch authsource to ldap ==" |
||||
mysql_q "UPDATE mailbox SET authsource='ldap' WHERE username='${MAILBOX}';" |
||||
AFTER=$(mysql_q "SELECT username, active, authsource FROM mailbox WHERE username='${MAILBOX}';") |
||||
echo "Mailbox after: $AFTER" |
||||
|
||||
echo "== SOGo static view (LDAP user) ==" |
||||
# LDAP users: clear local password hash in SOGo view; SOGo authenticates via LDAP |
||||
docker exec "$MYSQL_C" bash -lc "mysql mailcow -uroot -p\"\$MYSQL_ROOT_PASSWORD\" -e \" |
||||
UPDATE _sogo_static_view SET c_password = NULL WHERE c_name = '${MAILBOX}'; |
||||
\"" || echo "WARN: _sogo_static_view update skipped (table/row may differ)" |
||||
|
||||
echo "== Restart mail services ==" |
||||
cd "$STACK" |
||||
docker compose restart dovecot-mailcow sogo-mailcow |
||||
|
||||
echo "== fetchmail timer ==" |
||||
systemctl is-active fetchmail-support.timer |
||||
docker exec "$DOVECOT_C" doveadm mailbox status -u "$MAILBOX" messages INBOX 2>/dev/null || true |
||||
|
||||
echo "" |
||||
echo "DONE. Test IMAP with AD password for ${MAILBOX}" |
||||
echo "fetchmail POP3 drain unchanged (cPanel -> same inbox)" |
||||
@ -0,0 +1,18 @@
@@ -0,0 +1,18 @@
|
||||
#!/bin/bash |
||||
# Sync Let's Encrypt cert from nginx (.24) to Mailcow SMTP/IMAP (.28) |
||||
# Run from workstation with SSH to both hosts, or schedule after certbot renew on .24 |
||||
set -euo pipefail |
||||
|
||||
NGINX_HOST="${NGINX_HOST:-10.100.1.24}" |
||||
MAILCOW_HOST="${MAILCOW_HOST:-10.100.1.28}" |
||||
DOMAIN="${DOMAIN:-sync.geonet.co.id}" |
||||
STACK="/opt/stacks/mailcow" |
||||
CERT_SRC="/etc/letsencrypt/live/${DOMAIN}/fullchain.pem" |
||||
KEY_SRC="/etc/letsencrypt/live/${DOMAIN}/privkey.pem" |
||||
|
||||
echo "Copy LE cert ${DOMAIN} -> Mailcow ${MAILCOW_HOST}" |
||||
ssh root@"${NGINX_HOST}" "cat ${CERT_SRC}" | ssh root@"${MAILCOW_HOST}" "cat > ${STACK}/data/assets/ssl/cert.pem" |
||||
ssh root@"${NGINX_HOST}" "cat ${KEY_SRC}" | ssh root@"${MAILCOW_HOST}" "cat > ${STACK}/data/assets/ssl/key.pem" |
||||
ssh root@"${MAILCOW_HOST}" "chmod 600 ${STACK}/data/assets/ssl/key.pem && openssl x509 -in ${STACK}/data/assets/ssl/cert.pem -noout -issuer" |
||||
ssh root@"${MAILCOW_HOST}" "cd ${STACK} && docker compose restart postfix-mailcow dovecot-mailcow nginx-mailcow" |
||||
echo "DONE" |
||||
@ -0,0 +1,20 @@
@@ -0,0 +1,20 @@
|
||||
# MikroTik — template (AMAN di-commit) |
||||
# Credential SSH: key ~/.ssh/id_rsa_mikrotik — bukan di file ini |
||||
|
||||
MIKROTIK_HOST=10.100.1.1 |
||||
MIKROTIK_HOST_OFFICE=192.168.0.1 |
||||
MIKROTIK_SSH_PORT=255 |
||||
MIKROTIK_SSH_USER=admin |
||||
MIKROTIK_SSH_MAC=hmac-sha1 |
||||
|
||||
# WAN publik (blok ISP) |
||||
WAN_PUBLIC_BLOCK=117.102.73.96/29 |
||||
WAN_GATEWAY_ISP1=117.102.73.97 |
||||
WAN_IP_PRIMARY=117.102.73.102 |
||||
|
||||
# Segment internal |
||||
LAN_SERVER=10.100.1.0/24 |
||||
LAN_OFFICE=192.168.0.0/24 |
||||
LAN_VPN=100.100.1.0/24 |
||||
|
||||
# Dokumentasi: docs/server.md, docs/system-requirements.md |
||||
@ -0,0 +1,7 @@
@@ -0,0 +1,7 @@
|
||||
# Local secrets — never commit |
||||
.env |
||||
.env.* |
||||
!.env.example |
||||
|
||||
# Optional: full export with show-sensitive (if ever used) |
||||
backups/*-sensitive.rsc |
||||
@ -0,0 +1,36 @@
@@ -0,0 +1,36 @@
|
||||
# AGENTS.md — Cold Start |
||||
|
||||
> Project: `Mikrotik/` |
||||
> Sesi: [docs/ai-session-summary.md](./docs/ai-session-summary.md) |
||||
> Peta: [docs/context-index.md](./docs/context-index.md) |
||||
> Env: [.env.example](./.env.example) |
||||
|
||||
## Apa ini? |
||||
|
||||
Gateway perimeter GeoNet — MikroTik CCR2004 (`10.100.1.1`), NAT publik, dual-WAN hybrid failover, VPN, split-DNS. SSOT config backup & arsitektur. |
||||
|
||||
## Aturan kritis |
||||
|
||||
- SSH: **port 255**, `-m hmac-sha1`, key `~/.ssh/id_rsa_mikrotik` (lihat `server-connection/scripts/ssh-mikrotik.ps1`) |
||||
- **Jangan** commit password / `export show-sensitive` — redaksi `nasFtpPass` di backup `.rsc` |
||||
- Ubah routing/NAT hanya setelah backup + catat di `docs/version.md` |
||||
- DNS publik domain (SPF/DKIM) **bukan** di MikroTik — di registrar |
||||
- No commit kecuali user minta |
||||
- SSH oleh agent wajib persetujuan user |
||||
|
||||
## Lanjut kerja |
||||
|
||||
``` |
||||
1. AGENTS.md → docs/ai-session-summary.md → STOP |
||||
2. docs/architecture/system-overview.md, docs/server.md, backups/ |
||||
``` |
||||
|
||||
## Pointer |
||||
|
||||
| Butuh | Buka | |
||||
|-------|------| |
||||
| Arsitektur | [docs/architecture/system-overview.md](./docs/architecture/system-overview.md) | |
||||
| NAT mail `.28` | [docs/notes/nat-mail-gisportal.md](./docs/notes/nat-mail-gisportal.md) | |
||||
| Restore | [backups/README.md](./backups/README.md) | |
||||
| Script deploy | `server-connection/scripts/apply-failover-mikrotik.ps1` | |
||||
| Legacy audit | `server-connection/server/mikrotik-audit.txt` | |
||||
@ -0,0 +1,12 @@
@@ -0,0 +1,12 @@
|
||||
# MikroTik — Gateway GeoNet |
||||
|
||||
Router perimeter: NAT, dual-WAN hybrid, VPN, split-DNS. |
||||
|
||||
| Item | Nilai | |
||||
|------|-------| |
||||
| Model | CCR2004-1G-12S+2XS | |
||||
| RouterOS | 7.5 | |
||||
| SSH | `admin@10.100.1.1:255` + `-m hmac-sha1` | |
||||
| Backup repo | `backups/mikrotik-export-*.rsc` | |
||||
|
||||
**AI entry point:** [`docs/context-index.md`](docs/context-index.md) |
||||
@ -0,0 +1,34 @@
@@ -0,0 +1,34 @@
|
||||
# MikroTik Config Backups |
||||
|
||||
> **Jangan** commit file yang berisi `password=` / `show-sensitive`. |
||||
|
||||
## File |
||||
|
||||
| File | Tanggal | Keterangan | |
||||
|------|---------|------------| |
||||
| `mikrotik-export-2026-07-06.rsc` | 2026-07-06 | `/export compact` live dari `10.100.1.1` — password NAS script **diredaksi** | |
||||
|
||||
Backup harian otomatis juga ke QNAP: `mainpve/mikrotik/nas-latest.*` (scheduler `nas-backup-daily`). |
||||
|
||||
## Restore (uji di maintenance window) |
||||
|
||||
```bash |
||||
# Via SSH (port 255) |
||||
ssh -m hmac-sha1 -i ~/.ssh/id_rsa_mikrotik admin@10.100.1.1 -p 255 |
||||
|
||||
# Upload .rsc ke router lalu: |
||||
/import file-name=mikrotik-export-2026-07-06.rsc |
||||
``` |
||||
|
||||
Atau Winbox → Files → upload → Import. |
||||
|
||||
**Peringatan:** import penuh bisa menimpa konfigurasi live. Untuk restore parsial, edit `.rsc` atau gunakan `/system backup load` dari file `.backup` di NAS. |
||||
|
||||
## Regenerate backup ke repo |
||||
|
||||
```powershell |
||||
cd server-connection |
||||
.\scripts\ssh-mikrotik.ps1 -Command "/export compact" |
||||
# Salin output ke Mikrotik/backups/mikrotik-export-YYYY-MM-DD.rsc |
||||
# Redaksi nasFtpPass sebelum commit |
||||
``` |
||||
@ -0,0 +1,635 @@
@@ -0,0 +1,635 @@
|
||||
# jul/06/2026 15:46:32 by RouterOS 7.5 |
||||
# software id = E3H0-EVXR |
||||
# |
||||
# model = CCR2004-1G-12S+2XS |
||||
# serial number = HDD08647CP6 |
||||
/interface bridge |
||||
add name=office |
||||
add name=server |
||||
add add-dhcp-option82=yes dhcp-snooping=yes name=vpn |
||||
/interface ethernet |
||||
set [ find default-name=ether1 ] comment="ISP BIZNET" |
||||
set [ find default-name=sfp-sfpplus1 ] auto-negotiation=no comment=\ |
||||
"ISP IDBIZ" |
||||
set [ find default-name=sfp-sfpplus2 ] comment=DELL-main-netwokrkVMBR0 \ |
||||
loop-protect=on loop-protect-disable-time=10s |
||||
set [ find default-name=sfp-sfpplus3 ] comment=DELL loop-protect=on \ |
||||
loop-protect-disable-time=10s |
||||
set [ find default-name=sfp-sfpplus4 ] comment=IBM loop-protect=on \ |
||||
loop-protect-disable-time=10s |
||||
set [ find default-name=sfp-sfpplus5 ] comment=NAS |
||||
set [ find default-name=sfp-sfpplus6 ] auto-negotiation=no disabled=yes |
||||
set [ find default-name=sfp-sfpplus10 ] comment="swich server" |
||||
set [ find default-name=sfp-sfpplus11 ] comment="swich production" speed=\ |
||||
10Gbps |
||||
set [ find default-name=sfp-sfpplus12 ] comment="swich adm" speed=10Gbps |
||||
/interface vlan |
||||
add interface=sfp-sfpplus12 loop-protect=on name=vlan3 vlan-id=3 |
||||
add interface=sfp-sfpplus10 loop-protect=on name=vlan10 vlan-id=10 |
||||
add interface=sfp-sfpplus11 loop-protect=on name=vlan11 vlan-id=11 |
||||
add interface=sfp-sfpplus12 loop-protect=on name=vlan12 vlan-id=12 |
||||
add interface=sfp-sfpplus10 name=vlan99 vlan-id=99 |
||||
add disabled=yes interface=sfp-sfpplus10 loop-protect=on name=vlan2001 \ |
||||
vlan-id=2001 |
||||
add interface=sfp-sfpplus4 name=vlan2004 vlan-id=2001 |
||||
add interface=sfp-sfpplus10 loop-protect=on name=vlan2010 vlan-id=2010 |
||||
add interface=sfp-sfpplus12 loop-protect=on name=vlan2012 vlan-id=2012 |
||||
/interface wireless security-profiles |
||||
set [ find default=yes ] supplicant-identity=MikroTik |
||||
/ip pool |
||||
add name=dhcp_pool0 ranges=192.168.0.2-192.168.0.254 |
||||
add name=dhcp_pool1 ranges=192.168.0.2-192.168.0.254 |
||||
add name=dhcp_pool2 ranges=192.168.0.2-192.168.0.254 |
||||
add name=dhcp_pool3 ranges=192.168.0.2-192.168.0.254 |
||||
add name=dhcp_pool4 ranges=100.100.1.2-100.100.1.254 |
||||
add name=dhcp_pool5 ranges=192.168.2.2-192.168.2.254 |
||||
add name=dhcp_pool6 ranges=192.168.2.2-192.168.2.254 |
||||
/ip dhcp-server |
||||
add address-pool=dhcp_pool3 interface=office lease-time=4w3d name=dhcp1 |
||||
add address-pool=dhcp_pool4 interface=vpn name=dhcp2 |
||||
# DHCP server can not run on slave interface! |
||||
add address-pool=dhcp_pool6 interface=vlan2004 name=dhcp3 relay=192.168.2.1 |
||||
/port |
||||
set 0 name=serial0 |
||||
set 1 name=serial1 |
||||
/queue simple |
||||
add name=multimedia priority=1/1 target=192.168.0.4/32 |
||||
add disabled=yes name=priotiry priority=2/2 target=office |
||||
/routing table |
||||
add disabled=no fib name="KE ISP 1" |
||||
add disabled=no fib name="KE ISP 2" |
||||
/snmp community |
||||
set [ find default=yes ] write-access=yes |
||||
/interface bridge port |
||||
add bridge=server interface=sfp-sfpplus2 |
||||
add bridge=server interface=sfp-sfpplus3 |
||||
add bridge=server interface=sfp-sfpplus4 |
||||
add bridge=server interface=sfp-sfpplus5 |
||||
add bridge=office interface=sfp-sfpplus10 trusted=yes |
||||
add bridge=office interface=sfp-sfpplus11 trusted=yes |
||||
add bridge=office disabled=yes interface=sfp-sfpplus12 |
||||
add bridge=server interface=vlan10 |
||||
add bridge=server interface=vlan11 |
||||
add bridge=server interface=vlan12 |
||||
add bridge=server interface=vlan99 |
||||
add bridge=office interface=vlan2010 trusted=yes |
||||
add bridge=server interface=vlan3 |
||||
add bridge=office interface=vlan2012 trusted=yes |
||||
add bridge=office interface=vlan2004 trusted=yes |
||||
add bridge=server interface=sfp-sfpplus6 |
||||
/interface pptp-server server |
||||
# PPTP connections are considered unsafe, it is suggested to use a more modern VPN protocol instead |
||||
set enabled=yes |
||||
/interface sstp-server server |
||||
set enabled=yes |
||||
/ip address |
||||
add address=192.168.88.1/24 comment=defconf disabled=yes interface=ether1 \ |
||||
network=192.168.88.0 |
||||
add address=117.102.73.102/29 comment=gisportal.id interface=ether1 network=\ |
||||
117.102.73.96 |
||||
add address=117.102.73.101 comment="Not Set" interface=ether1 network=\ |
||||
117.102.73.101 |
||||
add address=117.102.73.100 comment=dev.gisportal.id interface=ether1 network=\ |
||||
117.102.73.100 |
||||
add address=117.102.73.98 comment=geonet.co.id interface=ether1 network=\ |
||||
117.102.73.96 |
||||
add address=10.100.1.1/24 interface=server network=10.100.1.0 |
||||
add address=117.102.73.99 comment=geonet.co.id interface=ether1 network=\ |
||||
117.102.73.99 |
||||
add address=192.168.0.1/24 interface=sfp-sfpplus10 network=192.168.0.0 |
||||
add address=100.100.1.0 interface=vpn network=100.100.1.0 |
||||
add address=192.168.2.0/24 interface=vlan2004 network=192.168.2.0 |
||||
/ip dhcp-client |
||||
add add-default-route=no interface=sfp-sfpplus1 use-peer-dns=no |
||||
/ip dhcp-server lease |
||||
add address=192.168.0.11 client-id=1:bc:fc:e7:8e:55:67 mac-address=\ |
||||
BC:FC:E7:8E:55:67 server=dhcp1 |
||||
add address=192.168.0.102 client-id=1:18:fb:7b:a5:50:8b mac-address=\ |
||||
18:FB:7B:A5:50:8B server=dhcp1 |
||||
add address=192.168.0.9 client-id=1:18:fd:74:52:8e:5f comment=swich \ |
||||
mac-address=18:FD:74:52:8E:5F server=dhcp1 |
||||
add address=192.168.0.8 client-id=1:18:fd:74:8b:b2:7f comment=swich \ |
||||
mac-address=18:FD:74:8B:B2:7F server=dhcp1 |
||||
add address=192.168.0.4 mac-address=10:5F:02:84:F0:2F server=dhcp1 |
||||
add address=192.168.0.10 client-id=1:24:5e:be:42:8f:a5 mac-address=\ |
||||
24:5E:BE:42:8F:A5 server=dhcp1 |
||||
add address=192.168.0.74 client-id=1:b4:2e:99:2a:30:4c mac-address=\ |
||||
B4:2E:99:2A:30:4C server=dhcp1 |
||||
add address=192.168.0.20 client-id=1:80:3f:5d:f9:c1:40 comment=WAVLINK \ |
||||
mac-address=80:3F:5D:F9:C1:40 server=dhcp1 |
||||
add address=192.168.0.57 client-id=1:bc:24:11:5d:58:56 mac-address=\ |
||||
BC:24:11:5D:58:56 server=dhcp1 |
||||
add address=192.168.0.13 client-id=1:a0:d3:65:73:c7:97 mac-address=\ |
||||
A0:D3:65:73:C7:97 server=dhcp1 |
||||
add address=192.168.0.18 client-id=1:10:ff:e0:3a:7d:15 mac-address=\ |
||||
10:FF:E0:3A:7D:15 server=dhcp1 |
||||
add address=192.168.0.64 client-id=1:72:7e:64:31:eb:13 mac-address=\ |
||||
72:7E:64:31:EB:13 server=dhcp1 |
||||
add address=192.168.0.80 client-id=1:0:1:f5:2:b:d1 mac-address=\ |
||||
00:01:F5:02:0B:D1 server=dhcp1 |
||||
add address=192.168.0.69 mac-address=40:A3:CC:B1:02:15 server=dhcp1 |
||||
/ip dhcp-server network |
||||
add address=100.100.1.0/24 dns-server=100.100.1.1 gateway=100.100.1.1 |
||||
add address=192.168.0.0/24 dns-server=203.142.82.222,203.142.84.222 gateway=\ |
||||
192.168.0.1 |
||||
add address=192.168.2.0/24 dns-server=8.8.8.8,8.8.1.1 gateway=192.168.2.1 |
||||
/ip dns |
||||
set allow-remote-requests=yes servers=203.142.82.222,203.142.84.222 |
||||
/ip dns static |
||||
add address=10.100.1.61 disabled=yes name=arcgisenterprise.gisportal.id |
||||
add address=10.100.1.72 name=aernd.gisportal.id |
||||
add address=10.100.1.25 name=database.gisportal.id |
||||
add address=10.100.1.24 comment="split-dns gisportal apex" name=gisportal.id |
||||
add address=10.100.1.24 comment="split-dns dockge" name=dockge.gisportal.id |
||||
add address=10.100.1.24 name=geonet.gisportal.id |
||||
add address=10.100.1.24 name=api.gisportal.id |
||||
add address=10.100.1.25 comment="split-dns database regexp" regexp=\ |
||||
"^database\\.gisportal\\.id" |
||||
add address=10.100.1.72 comment="split-dns aernd regexp" regexp=\ |
||||
"^aernd\\.gisportal\\.id" |
||||
add address=10.100.1.51 comment="split-dns dev regexp" regexp=\ |
||||
"^dev\\.gisportal\\.id" |
||||
add address=10.100.1.24 comment="split-dns gisportal catch-all" regexp=\ |
||||
"\\.gisportal\\.id" |
||||
add address=10.100.1.24 comment="split-dns iguf" name=iguf.geonet.co.id |
||||
add address=10.100.1.24 comment=geonetagent-collector name=\ |
||||
collector.gisportal.id |
||||
add address=10.100.1.24 comment=geonetagent-agent name=agent.gisportal.id |
||||
/ip firewall address-list |
||||
add address=10.100.1.101 list=blocked-internet |
||||
add address=10.100.1.100 list=blocked-internet |
||||
add address=10.100.1.88 list=blocked-internet |
||||
add address=10.100.1.84 list=blocked-internet |
||||
add address=10.100.1.91 list=blocked-internet |
||||
add address=10.100.1.61 list=blocked-internet |
||||
add address=10.100.1.72 list=blocked-internet |
||||
add address=10.100.1.80 list=blocked-internet |
||||
add address=10.100.1.40 list=blocked-internet |
||||
add address=10.100.1.51 list=blocked-internet |
||||
add address=10.100.1.25 list=blocked-internet |
||||
add address=10.100.1.56 list=blocked-internet |
||||
add address=10.100.1.58 list=blocked-internet |
||||
add address=10.100.1.55 list=blocked-internet |
||||
add address=10.100.1.53 list=blocked-internet |
||||
/ip firewall filter |
||||
add action=drop chain=forward connection-state=new dst-address-list=ddosed \ |
||||
src-address-list=ddoser |
||||
add action=jump chain=forward connection-state=new jump-target=detect-ddos |
||||
add action=return chain=detect-ddos dst-limit=32,32,src-and-dst-addresses/1s |
||||
add action=add-dst-to-address-list address-list=ddosed address-list-timeout=\ |
||||
10m chain=detect-ddos |
||||
add action=add-src-to-address-list address-list=ddoser address-list-timeout=\ |
||||
10m chain=detect-ddos |
||||
add action=drop chain=forward comment=block-internet-biznet disabled=yes \ |
||||
out-interface=ether1 src-address-list=blocked-internet |
||||
add action=drop chain=forward comment=block-internet-idbiz disabled=yes \ |
||||
out-interface=sfp-sfpplus1 src-address-list=blocked-internet |
||||
/ip firewall mangle |
||||
add action=accept chain=prerouting comment="hybrid server-local-bypass" \ |
||||
dst-address=10.100.1.0/24 src-address=10.100.1.0/24 |
||||
add action=accept chain=prerouting comment="hybrid server-to-office-bypass" \ |
||||
dst-address=192.168.0.0/24 src-address=10.100.1.0/24 |
||||
add action=accept chain=prerouting comment="hybrid server-to-vpn-bypass" \ |
||||
dst-address=100.100.1.0/24 src-address=10.100.1.0/24 |
||||
add action=accept chain=prerouting comment="hybrid mgmt bypass laptop" \ |
||||
disabled=yes src-address=192.168.0.33 |
||||
add action=accept chain=prerouting comment="hybrid mgmt bypass laptop" \ |
||||
src-address=10.100.1.220 |
||||
add action=accept chain=prerouting comment="hybrid server hairpin bypass" \ |
||||
dst-address=117.102.73.96/29 src-address=10.100.1.0/24 |
||||
add action=mark-routing chain=prerouting comment=temp-speedtest-isp2 \ |
||||
disabled=yes new-routing-mark="KE ISP 2" passthrough=yes src-address=\ |
||||
10.100.1.24 |
||||
add action=mark-routing chain=prerouting comment="hybrid server force ISP1" \ |
||||
new-routing-mark="KE ISP 1" passthrough=no src-address=10.100.1.0/24 |
||||
add action=mark-connection chain=prerouting connection-mark=no-mark disabled=\ |
||||
yes in-interface=vlan2004 new-connection-mark="ISP 2" passthrough=yes \ |
||||
per-connection-classifier=both-addresses-and-ports:2/1 |
||||
add action=mark-connection chain=prerouting connection-mark=no-mark disabled=\ |
||||
yes in-interface=server new-connection-mark="ISP 1" passthrough=yes \ |
||||
per-connection-classifier=both-addresses-and-ports:2/0 |
||||
add action=mark-routing chain=prerouting connection-mark="ISP 2" disabled=yes \ |
||||
in-interface=vlan2004 new-routing-mark="KE ISP 2" passthrough=yes \ |
||||
per-connection-classifier=both-addresses-and-ports:2/1 |
||||
add action=mark-connection chain=prerouting connection-mark=no-mark disabled=\ |
||||
yes in-interface=sfp-sfpplus1 new-connection-mark="ISP 2" passthrough=yes |
||||
add action=mark-connection chain=prerouting connection-mark=no-mark disabled=\ |
||||
yes in-interface=ether1 new-connection-mark="ISP 1" passthrough=yes |
||||
add action=mark-routing chain=output connection-mark="ISP 2" disabled=yes \ |
||||
new-routing-mark="KE ISP 2" passthrough=yes |
||||
add action=accept chain=prerouting comment="hybrid office-to-server-bypass" \ |
||||
dst-address=10.100.1.0/24 in-interface=office |
||||
add action=accept chain=prerouting comment="hybrid office hairpin bypass" \ |
||||
dst-address=117.102.73.96/29 in-interface=office |
||||
add action=mark-connection chain=prerouting comment="hybrid office PCC ISP1" \ |
||||
connection-mark=no-mark in-interface=office new-connection-mark="ISP 1" \ |
||||
passthrough=yes per-connection-classifier=both-addresses-and-ports:2/0 |
||||
add action=mark-connection chain=prerouting comment="hybrid office PCC ISP2" \ |
||||
connection-mark=no-mark in-interface=office new-connection-mark="ISP 2" \ |
||||
passthrough=yes per-connection-classifier=both-addresses-and-ports:2/1 |
||||
add action=accept chain=prerouting comment="hybrid vpn hairpin bypass" \ |
||||
dst-address=117.102.73.96/29 src-address=100.100.1.0/24 |
||||
add action=mark-connection chain=prerouting comment="hybrid vpn PCC ISP1" \ |
||||
connection-mark=no-mark disabled=yes in-interface=vpn \ |
||||
new-connection-mark="ISP 1" passthrough=yes per-connection-classifier=\ |
||||
both-addresses-and-ports:2/0 |
||||
add action=mark-connection chain=prerouting comment="hybrid vpn PCC ISP2" \ |
||||
connection-mark=no-mark disabled=yes in-interface=vpn \ |
||||
new-connection-mark="ISP 2" passthrough=yes per-connection-classifier=\ |
||||
both-addresses-and-ports:2/1 |
||||
add action=mark-routing chain=prerouting comment="hybrid route ISP1" \ |
||||
connection-mark="ISP 1" new-routing-mark="KE ISP 1" passthrough=yes |
||||
add action=mark-routing chain=prerouting comment="hybrid route ISP2" \ |
||||
connection-mark="ISP 2" new-routing-mark="KE ISP 2" passthrough=yes |
||||
/ip firewall nat |
||||
add action=masquerade chain=srcnat out-interface=ether1 |
||||
add action=masquerade chain=srcnat out-interface=sfp-sfpplus1 |
||||
add action=masquerade chain=srcnat |
||||
add action=dst-nat chain=dstnat dst-address=117.102.73.102 dst-port=80 \ |
||||
protocol=tcp to-addresses=10.100.1.24 to-ports=80 |
||||
add action=dst-nat chain=dstnat disabled=yes dst-address=117.102.73.101 \ |
||||
dst-port=80 protocol=tcp to-addresses=10.100.1.24 to-ports=80 |
||||
add action=dst-nat chain=dstnat dst-address=117.102.73.101 dst-port=80 \ |
||||
protocol=tcp to-addresses=10.100.1.76 to-ports=80 |
||||
add action=dst-nat chain=dstnat dst-address=117.102.73.99 dst-port=25 \ |
||||
protocol=tcp to-addresses=10.100.1.76 to-ports=25 |
||||
add action=dst-nat chain=dstnat dst-address=117.102.73.101 dst-port=25 \ |
||||
protocol=tcp to-addresses=10.100.1.76 to-ports=25 |
||||
add action=dst-nat chain=dstnat dst-address=117.102.73.101 dst-port=143 \ |
||||
protocol=tcp to-addresses=10.100.1.76 to-ports=143 |
||||
add action=dst-nat chain=dstnat dst-address=117.102.73.99 dst-port=143 \ |
||||
protocol=tcp to-addresses=10.100.1.76 to-ports=143 |
||||
add action=dst-nat chain=dstnat dst-address=117.102.73.101 dst-port=993 \ |
||||
protocol=tcp to-addresses=10.100.1.76 to-ports=993 |
||||
add action=dst-nat chain=dstnat dst-address=117.102.73.99 dst-port=993 \ |
||||
protocol=tcp to-addresses=10.100.1.76 to-ports=993 |
||||
add action=dst-nat chain=dstnat dst-address=117.102.73.101 dst-port=587 \ |
||||
protocol=tcp to-addresses=10.100.1.76 to-ports=587 |
||||
add action=dst-nat chain=dstnat dst-address=117.102.73.99 dst-port=587 \ |
||||
protocol=tcp to-addresses=10.100.1.76 to-ports=587 |
||||
add action=dst-nat chain=dstnat disabled=yes dst-address=117.102.73.101 \ |
||||
dst-port=443 protocol=tcp to-addresses=10.100.1.24 to-ports=443 |
||||
add action=dst-nat chain=dstnat dst-address=117.102.73.102 dst-port=24 \ |
||||
protocol=tcp to-addresses=10.100.1.24 to-ports=22 |
||||
add action=dst-nat chain=dstnat dst-address=117.102.73.102 dst-port=21 \ |
||||
protocol=tcp to-addresses=10.100.1.10 to-ports=21 |
||||
add action=dst-nat chain=dstnat dst-address=117.102.73.102 dst-port=443 \ |
||||
protocol=tcp to-addresses=10.100.1.24 to-ports=443 |
||||
add action=dst-nat chain=dstnat dst-address=117.102.73.99 dst-port=443 \ |
||||
protocol=tcp to-addresses=10.100.1.24 to-ports=443 |
||||
add action=dst-nat chain=dstnat dst-address=117.102.73.99 dst-port=80 \ |
||||
protocol=tcp to-addresses=10.100.1.24 to-ports=80 |
||||
add action=dst-nat chain=dstnat dst-address=117.102.73.100 dst-port=443 \ |
||||
protocol=tcp to-addresses=10.100.1.51 to-ports=443 |
||||
add action=dst-nat chain=dstnat dst-address=117.102.73.102 dst-port=1433 \ |
||||
protocol=tcp to-addresses=10.100.1.25 to-ports=1433 |
||||
add action=dst-nat chain=dstnat comment="rnd SQL Server 2016" dst-address=\ |
||||
117.102.73.102 dst-port=1434 protocol=tcp to-addresses=10.100.1.75 \ |
||||
to-ports=1433 |
||||
add action=dst-nat chain=dstnat comment="Zabbiz agenet active" dst-address=\ |
||||
117.102.73.102 dst-port=10051 protocol=tcp to-addresses=10.100.1.42 \ |
||||
to-ports=10051 |
||||
add action=dst-nat chain=dstnat comment="rnd SQL Server 2022" dst-address=\ |
||||
117.102.73.102 dst-port=1437 protocol=tcp to-addresses=10.100.1.77 \ |
||||
to-ports=1433 |
||||
add action=dst-nat chain=dstnat comment="rnd SQL Server 2016" dst-address=\ |
||||
117.102.73.102 dst-port=1436 protocol=tcp to-addresses=10.100.1.76 \ |
||||
to-ports=1433 |
||||
add action=dst-nat chain=dstnat dst-address=117.102.73.102 dst-port=5432 \ |
||||
protocol=tcp to-addresses=10.100.1.25 to-ports=5432 |
||||
add action=dst-nat chain=dstnat dst-address=117.102.73.99 dst-port=8080 \ |
||||
protocol=tcp to-addresses=10.100.1.27 to-ports=8080 |
||||
add action=dst-nat chain=dstnat dst-address=117.102.73.102 dst-port=5434 \ |
||||
protocol=tcp to-addresses=10.100.1.27 to-ports=5434 |
||||
add action=dst-nat chain=dstnat dst-address=117.102.73.100 dst-port=30443 \ |
||||
protocol=tcp to-addresses=10.100.1.59 to-ports=30443 |
||||
add action=dst-nat chain=dstnat dst-address=117.102.73.100 dst-port=6143 \ |
||||
protocol=tcp to-addresses=10.100.1.59 to-ports=6143 |
||||
add action=dst-nat chain=dstnat dst-address=117.102.73.100 dst-port=13443 \ |
||||
protocol=tcp to-addresses=10.100.1.57 to-ports=13443 |
||||
add action=dst-nat chain=dstnat dst-address=117.102.73.100 dst-port=6443 \ |
||||
protocol=tcp to-addresses=10.100.1.51 to-ports=6443 |
||||
add action=dst-nat chain=dstnat dst-address=117.102.73.100 dst-port=80 \ |
||||
protocol=tcp to-addresses=10.100.1.51 to-ports=80 |
||||
add action=dst-nat chain=dstnat dst-address=117.102.73.100 dst-port=7443 \ |
||||
protocol=tcp to-addresses=10.100.1.51 to-ports=7443 |
||||
add action=dst-nat chain=dstnat dst-address=117.102.73.100 dst-port=2443 \ |
||||
protocol=tcp to-addresses=10.100.1.51 to-ports=2443 |
||||
add action=dst-nat chain=dstnat dst-address=117.102.73.102 dst-port=5433 \ |
||||
protocol=tcp to-addresses=10.100.1.27 to-ports=5432 |
||||
add action=dst-nat chain=dstnat dst-address=117.102.73.102 dst-port=25 \ |
||||
protocol=tcp to-addresses=10.100.1.28 to-ports=25 |
||||
add action=dst-nat chain=dstnat dst-address=117.102.73.102 dst-port=993 \ |
||||
protocol=tcp to-addresses=10.100.1.28 to-ports=993 |
||||
add action=dst-nat chain=dstnat dst-address=117.102.73.102 dst-port=587 \ |
||||
protocol=tcp to-addresses=10.100.1.28 to-ports=587 |
||||
add action=dst-nat chain=dstnat dst-address=117.102.73.102 dst-port=465 \ |
||||
protocol=tcp to-addresses=10.100.1.28 to-ports=465 |
||||
add action=dst-nat chain=dstnat comment=geonet.co.id disabled=yes \ |
||||
dst-address=117.102.73.99 dst-port=25 protocol=tcp to-addresses=\ |
||||
10.100.1.40 to-ports=25 |
||||
add action=dst-nat chain=dstnat dst-address=117.102.73.102 dst-port=995 \ |
||||
protocol=tcp to-addresses=10.100.1.40 to-ports=995 |
||||
add action=dst-nat chain=dstnat comment=geonet.co.id disabled=yes \ |
||||
dst-address=117.102.73.99 dst-port=995 protocol=tcp to-addresses=\ |
||||
10.100.1.40 to-ports=995 |
||||
add action=dst-nat chain=dstnat disabled=yes dst-address=117.102.73.102 \ |
||||
dst-port=25 protocol=udp to-addresses=10.100.1.40 to-ports=25 |
||||
add action=dst-nat chain=dstnat dst-address=117.102.73.102 dst-port=587 \ |
||||
protocol=tcp to-addresses=10.100.1.40 to-ports=587 |
||||
add action=dst-nat chain=dstnat comment=geonet.co.id disabled=yes \ |
||||
dst-address=117.102.73.99 dst-port=587 protocol=tcp to-addresses=\ |
||||
10.100.1.40 to-ports=587 |
||||
add action=dst-nat chain=dstnat disabled=yes dst-address=117.102.73.102 \ |
||||
dst-port=587 protocol=udp to-addresses=10.100.1.40 to-ports=587 |
||||
add action=dst-nat chain=dstnat dst-address=117.102.73.102 dst-port=389 \ |
||||
protocol=tcp to-addresses=10.100.1.40 to-ports=389 |
||||
add action=dst-nat chain=dstnat comment=geonet.co.id disabled=yes \ |
||||
dst-address=117.102.73.99 dst-port=389 protocol=tcp to-addresses=\ |
||||
10.100.1.40 to-ports=389 |
||||
add action=dst-nat chain=dstnat disabled=yes dst-address=117.102.73.102 \ |
||||
dst-port=389 protocol=udp to-addresses=10.100.1.40 to-ports=389 |
||||
add action=dst-nat chain=dstnat disabled=yes dst-address=117.102.73.102 \ |
||||
dst-port=143 protocol=udp to-addresses=10.100.1.40 to-ports=143 |
||||
add action=dst-nat chain=dstnat dst-address=117.102.73.102 dst-port=143 \ |
||||
protocol=tcp to-addresses=10.100.1.40 to-ports=143 |
||||
add action=dst-nat chain=dstnat comment=geonet.co.id disabled=yes \ |
||||
dst-address=117.102.73.99 dst-port=143 protocol=tcp to-addresses=\ |
||||
10.100.1.40 to-ports=143 |
||||
add action=dst-nat chain=dstnat disabled=yes dst-address=117.102.73.102 \ |
||||
dst-port=110 protocol=udp to-addresses=10.100.1.40 to-ports=110 |
||||
add action=dst-nat chain=dstnat dst-address=117.102.73.102 dst-port=110 \ |
||||
protocol=tcp to-addresses=10.100.1.40 to-ports=110 |
||||
add action=dst-nat chain=dstnat comment=geonet.co.id disabled=yes \ |
||||
dst-address=117.102.73.99 dst-port=110 protocol=tcp to-addresses=\ |
||||
10.100.1.40 to-ports=110 |
||||
add action=masquerade chain=srcnat comment="Hairpin NAT" dst-address=\ |
||||
10.100.1.24 dst-port=443 out-interface=ether1 protocol=tcp src-address=\ |
||||
192.168.0.0/24 |
||||
add action=masquerade chain=srcnat comment="Hairpin NAT" dst-address=\ |
||||
10.100.1.100 dst-port=443 out-interface=ether1 protocol=tcp src-address=\ |
||||
192.168.0.0/24 |
||||
add action=masquerade chain=srcnat comment="Hairpin NAT" dst-address=\ |
||||
10.100.1.24 dst-port=80 out-interface=ether1 protocol=tcp src-address=\ |
||||
192.168.0.0/24 |
||||
add action=dst-nat chain=dstnat dst-address=117.102.73.101 dst-port=995 \ |
||||
protocol=tcp to-addresses=10.100.1.76 to-ports=995 |
||||
add action=dst-nat chain=dstnat dst-address=117.102.73.99 dst-port=995 \ |
||||
protocol=tcp to-addresses=10.100.1.76 to-ports=995 |
||||
add action=dst-nat chain=dstnat dst-address=117.102.73.101 dst-port=465 \ |
||||
protocol=tcp to-addresses=10.100.1.76 to-ports=465 |
||||
add action=dst-nat chain=dstnat dst-address=117.102.73.99 dst-port=465 \ |
||||
protocol=tcp to-addresses=10.100.1.76 to-ports=465 |
||||
add action=dst-nat chain=dstnat dst-address=117.102.73.99 dst-port=993 \ |
||||
protocol=tcp to-addresses=10.100.1.76 to-ports=993 |
||||
add action=masquerade chain=srcnat comment=hairpin-10.100.1-nginx-443 \ |
||||
dst-address=10.100.1.24 dst-port=443 protocol=tcp src-address=\ |
||||
10.100.1.0/24 |
||||
add action=masquerade chain=srcnat comment=hairpin-10.100.1-nginx-80 \ |
||||
dst-address=10.100.1.24 dst-port=80 protocol=tcp src-address=\ |
||||
10.100.1.0/24 |
||||
add action=masquerade chain=srcnat comment=hairpin-vpn-nginx-443 dst-address=\ |
||||
10.100.1.24 dst-port=443 protocol=tcp src-address=100.100.1.0/24 |
||||
add action=masquerade chain=srcnat comment=hairpin-vpn-nginx-80 dst-address=\ |
||||
10.100.1.24 dst-port=80 protocol=tcp src-address=100.100.1.0/24 |
||||
add action=dst-nat chain=dstnat comment=ssh-mikrotik-public-102 dst-address=\ |
||||
117.102.73.102 dst-port=255 protocol=tcp to-addresses=10.100.1.1 \ |
||||
to-ports=255 |
||||
add action=dst-nat chain=dstnat comment=ssh-nginx-public-22 disabled=yes \ |
||||
dst-address=117.102.73.102 dst-port=22 protocol=tcp to-addresses=\ |
||||
10.100.1.24 to-ports=22 |
||||
add action=masquerade chain=srcnat comment=hairpin-ssh-mikrotik dst-address=\ |
||||
10.100.1.1 dst-port=255 protocol=tcp src-address=10.100.1.0/24 |
||||
add action=masquerade chain=srcnat comment=hairpin-ssh-nginx disabled=yes \ |
||||
dst-address=10.100.1.24 dst-port=22 protocol=tcp src-address=\ |
||||
10.100.1.0/24 |
||||
add action=masquerade chain=srcnat comment=hairpin-ssh-mikrotik-office \ |
||||
dst-address=10.100.1.1 dst-port=255 protocol=tcp src-address=\ |
||||
192.168.0.0/24 |
||||
add action=masquerade chain=srcnat comment=hairpin-ssh-nginx-office disabled=\ |
||||
yes dst-address=10.100.1.24 dst-port=22 protocol=tcp src-address=\ |
||||
192.168.0.0/24 |
||||
add action=dst-nat chain=dstnat comment=ssh-public-db dst-address=\ |
||||
117.102.73.102 dst-port=225 protocol=tcp to-addresses=10.100.1.25 \ |
||||
to-ports=22 |
||||
add action=masquerade chain=srcnat comment=hairpin-ssh-public-db dst-address=\ |
||||
10.100.1.25 dst-port=22 protocol=tcp src-address=10.100.1.0/24 |
||||
add action=masquerade chain=srcnat comment=hairpin-ssh-public-db-office \ |
||||
dst-address=10.100.1.25 dst-port=22 protocol=tcp src-address=\ |
||||
192.168.0.0/24 |
||||
/ip route |
||||
add check-gateway=ping comment="hybrid failover ISP1 primary" disabled=no \ |
||||
distance=1 dst-address=0.0.0.0/0 gateway=117.102.73.97 pref-src="" \ |
||||
routing-table=main scope=30 suppress-hw-offload=no target-scope=10 |
||||
add check-gateway=none comment="hybrid ISP2" disabled=no distance=1 \ |
||||
dst-address=0.0.0.0/0 gateway=192.168.1.1 pref-src="" routing-table=\ |
||||
"KE ISP 2" scope=30 suppress-hw-offload=no target-scope=10 |
||||
add check-gateway=ping comment="hybrid failover ISP2 backup" disabled=no \ |
||||
distance=2 dst-address=0.0.0.0/0 gateway=192.168.1.1 routing-table=main |
||||
add check-gateway=none comment="hybrid ISP1" disabled=no distance=1 \ |
||||
dst-address=0.0.0.0/0 gateway=117.102.73.97 routing-table="KE ISP 1" |
||||
add comment="hybrid ISP1 WAN lan" distance=1 dst-address=117.102.73.96/29 \ |
||||
gateway=ether1 routing-table="KE ISP 1" |
||||
add comment="hybrid ISP2 WAN lan" distance=1 dst-address=192.168.1.0/24 \ |
||||
gateway=sfp-sfpplus1 routing-table="KE ISP 2" |
||||
add comment="hybrid office lan ISP1" distance=1 dst-address=192.168.0.0/24 \ |
||||
gateway=office routing-table="KE ISP 1" |
||||
add comment="hybrid office lan ISP2" distance=1 dst-address=192.168.0.0/24 \ |
||||
gateway=office routing-table="KE ISP 2" |
||||
/ip service |
||||
set telnet disabled=yes |
||||
set ftp disabled=yes |
||||
set www disabled=yes |
||||
set ssh port=255 |
||||
set api disabled=yes |
||||
set winbox address=10.100.1.0/24,192.168.0.0/24 |
||||
set api-ssl disabled=yes |
||||
/ppp aaa |
||||
set use-radius=yes |
||||
/ppp secret |
||||
add local-address=10.100.1.1 name=rbsetiawan remote-address=10.100.1.220 |
||||
add local-address=10.100.1.1 name=asobari remote-address=10.100.1.225 |
||||
add local-address=10.100.1.1 name=uabdurrohman remote-address=10.100.1.226 |
||||
add local-address=10.100.1.1 name=trachman remote-address=10.100.1.227 |
||||
add local-address=10.100.1.1 name=test remote-address=10.100.1.211 |
||||
add local-address=10.100.1.1 name=dpradana remote-address=10.100.1.228 |
||||
add local-address=10.100.1.1 name=ataufik remote-address=10.100.1.229 |
||||
add local-address=10.100.1.1 name=awrahajeng remote-address=10.100.1.230 |
||||
/radius |
||||
add address=10.100.1.40 domain=gisportal.id service=ppp src-address=\ |
||||
10.100.1.1 |
||||
/routing rule |
||||
add action=lookup comment="hybrid ISP1" routing-mark="KE ISP 1" table=\ |
||||
"KE ISP 1" |
||||
add action=lookup comment="hybrid ISP2" routing-mark="KE ISP 2" table=\ |
||||
"KE ISP 2" |
||||
/snmp |
||||
set enabled=yes |
||||
/system clock |
||||
set time-zone-name=Asia/Jakarta |
||||
/system scheduler |
||||
add comment="hybrid scheduler" interval=1m name=hybrid-sync-mode on-event=\ |
||||
hybrid-sync-mode policy=\ |
||||
ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ |
||||
start-date=jun/13/2026 start-time=17:41:40 |
||||
add comment="Monitor latency ISP1 vs ISP2" interval=2m name=latency-monitor \ |
||||
on-event=latency-monitor policy=\ |
||||
ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ |
||||
start-time=startup |
||||
add comment="Backup config ke QNAP 10.100.1.10" interval=1d name=\ |
||||
nas-backup-daily on-event=nas-backup policy=\ |
||||
ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ |
||||
start-date=jun/15/2026 start-time=03:00:00 |
||||
/system script |
||||
add dont-require-permissions=yes name=hybrid-set-mode-both-up owner=admin \ |
||||
policy=read,write,test source="\r\ |
||||
\n/ip firewall mangle enable [find comment=\"hybrid office PCC ISP1\"]\r\ |
||||
\n/ip firewall mangle enable [find comment=\"hybrid office PCC ISP2\"]\r\ |
||||
\n/ip firewall mangle disable [find comment=\"hybrid vpn PCC ISP1\"]\r\ |
||||
\n/ip firewall mangle disable [find comment=\"hybrid vpn PCC ISP2\"]\r\ |
||||
\n/ip firewall mangle enable [find comment=\"hybrid route ISP1\"]\r\ |
||||
\n/ip firewall mangle enable [find comment=\"hybrid route ISP2\"]\r\ |
||||
\n:log info \"HYBRID: mode BOTH-UP (office PCC 50/50, VPN failover only)\"\ |
||||
\r\ |
||||
\n" |
||||
add dont-require-permissions=yes name=hybrid-set-mode-isp1-down owner=admin \ |
||||
policy=read,write,test source="\r\ |
||||
\n/ip firewall mangle disable [find comment=\"hybrid office PCC ISP1\"]\r\ |
||||
\n/ip firewall mangle disable [find comment=\"hybrid office PCC ISP2\"]\r\ |
||||
\n/ip firewall mangle disable [find comment=\"hybrid vpn PCC ISP1\"]\r\ |
||||
\n/ip firewall mangle disable [find comment=\"hybrid vpn PCC ISP2\"]\r\ |
||||
\n/ip firewall mangle disable [find comment=\"hybrid route ISP1\"]\r\ |
||||
\n/ip firewall mangle disable [find comment=\"hybrid route ISP2\"]\r\ |
||||
\n:log info \"HYBRID: mode ISP1-DOWN\"\r\ |
||||
\n" |
||||
add dont-require-permissions=yes name=hybrid-set-mode-isp2-down owner=admin \ |
||||
policy=read,write,test source="\r\ |
||||
\n/ip firewall mangle disable [find comment=\"hybrid office PCC ISP2\"]\r\ |
||||
\n/ip firewall mangle disable [find comment=\"hybrid vpn PCC ISP2\"]\r\ |
||||
\n/ip firewall mangle disable [find comment=\"hybrid route ISP2\"]\r\ |
||||
\n/ip firewall mangle enable [find comment=\"hybrid office PCC ISP1\"]\r\ |
||||
\n/ip firewall mangle disable [find comment=\"hybrid vpn PCC ISP1\"]\r\ |
||||
\n/ip firewall mangle enable [find comment=\"hybrid route ISP1\"]\r\ |
||||
\n:log info \"HYBRID: mode ISP2-DOWN (office ISP1 only, VPN failover only)\ |
||||
\"\r\ |
||||
\n" |
||||
add dont-require-permissions=yes name=hybrid-sync-mode owner=admin policy=\ |
||||
read,write,test,sniff source="\r\ |
||||
\n:local up1 false\r\ |
||||
\n:local up2 false\r\ |
||||
\n:local ok1 0\r\ |
||||
\n:local ok2 0\r\ |
||||
\n:for i from=1 to=3 do={\r\ |
||||
\n :local r1 [/ping 117.102.73.97 count=1 as-value]\r\ |
||||
\n :if ([:typeof (\$r1->\"time\")] != \"nothing\") do={ :set ok1 (\$ok1 +\ |
||||
\_1) }\r\ |
||||
\n :local r2 [/ping 192.168.1.1 count=1 as-value]\r\ |
||||
\n :if ([:typeof (\$r2->\"time\")] != \"nothing\") do={ :set ok2 (\$ok2 +\ |
||||
\_1) }\r\ |
||||
\n}\r\ |
||||
\n:if (\$ok1 >= 2) do={ :set up1 true }\r\ |
||||
\n:if (\$ok2 >= 2) do={ :set up2 true }\r\ |
||||
\n:if (\$up1 && \$up2) do={\r\ |
||||
\n /system script run hybrid-set-mode-both-up\r\ |
||||
\n} else={\r\ |
||||
\n :if (!\$up1) do={\r\ |
||||
\n /system script run hybrid-set-mode-isp1-down\r\ |
||||
\n } else={\r\ |
||||
\n :if (!\$up2) do={\r\ |
||||
\n /system script run hybrid-set-mode-isp2-down\r\ |
||||
\n }\r\ |
||||
\n }\r\ |
||||
\n}\r\ |
||||
\n" |
||||
add dont-require-permissions=yes name=latency-monitor owner=admin policy=\ |
||||
read,write,test,sniff source="\r\ |
||||
\n:local hysteresis 10ms\r\ |
||||
\n:global bestWan\r\ |
||||
\n:global isp1Latency\r\ |
||||
\n:global isp2Latency\r\ |
||||
\n:global isp1Loss\r\ |
||||
\n:global isp2Loss\r\ |
||||
\n:if ([:typeof \$bestWan] = \"nothing\") do={ :set bestWan \"isp1\" }\r\ |
||||
\n:local t1 0ms\r\ |
||||
\n:local t2 0ms\r\ |
||||
\n:local ok1 0\r\ |
||||
\n:local ok2 0\r\ |
||||
\n:local i 0\r\ |
||||
\n:do {\r\ |
||||
\n :local r1 [/ping 117.102.73.97 count=1 as-value]\r\ |
||||
\n :if ([:typeof (\$r1->\"time\")] != \"nothing\") do={\r\ |
||||
\n :set t1 (\$t1 + (\$r1->\"time\"))\r\ |
||||
\n :set ok1 (\$ok1 + 1)\r\ |
||||
\n }\r\ |
||||
\n :local r2 [/ping 192.168.1.1 count=1 as-value]\r\ |
||||
\n :if ([:typeof (\$r2->\"time\")] != \"nothing\") do={\r\ |
||||
\n :set t2 (\$t2 + (\$r2->\"time\"))\r\ |
||||
\n :set ok2 (\$ok2 + 1)\r\ |
||||
\n }\r\ |
||||
\n :set i (\$i + 1)\r\ |
||||
\n} while=(\$i < 5)\r\ |
||||
\n:local avg1 9999ms\r\ |
||||
\n:local avg2 9999ms\r\ |
||||
\n:local loss1 100\r\ |
||||
\n:local loss2 100\r\ |
||||
\n:if (\$ok1 > 0) do={\r\ |
||||
\n :set avg1 (\$t1 / \$ok1)\r\ |
||||
\n :set loss1 (100 - ((\$ok1 * 100) / 5))\r\ |
||||
\n}\r\ |
||||
\n:if (\$ok2 > 0) do={\r\ |
||||
\n :set avg2 (\$t2 / \$ok2)\r\ |
||||
\n :set loss2 (100 - ((\$ok2 * 100) / 5))\r\ |
||||
\n}\r\ |
||||
\n:set isp1Latency \$avg1\r\ |
||||
\n:set isp2Latency \$avg2\r\ |
||||
\n:set isp1Loss \$loss1\r\ |
||||
\n:set isp2Loss \$loss2\r\ |
||||
\n:local newBest \$bestWan\r\ |
||||
\n:if (\$loss1>49 && \$loss2>49) do={\r\ |
||||
\n :log warning \"Latency Monitor: kedua ISP loss tinggi, tetap \$bestWan\ |
||||
\"\r\ |
||||
\n} else={\r\ |
||||
\n :if (\$loss2>49) do={ :set newBest \"isp1\" } else={\r\ |
||||
\n :if (\$loss1>49) do={ :set newBest \"isp2\" } else={\r\ |
||||
\n :if (\$avg1 < (\$avg2 - \$hysteresis)) do={ :set newBest \"isp1\" \ |
||||
} else={\r\ |
||||
\n :if (\$avg1 > (\$avg2 + \$hysteresis)) do={ :set newBest \"isp2\ |
||||
\" }\r\ |
||||
\n }\r\ |
||||
\n }\r\ |
||||
\n }\r\ |
||||
\n :set bestWan \$newBest\r\ |
||||
\n}\r\ |
||||
\n:log info (\"Latency Monitor: ISP1=\" . [:tostr \$avg1] . \" loss=\" . \ |
||||
\$loss1 . \"% | ISP2=\" . [:tostr \$avg2] . \" loss=\" . \$loss2 . \"% | b\ |
||||
est=\" . \$bestWan)\r\ |
||||
\n" |
||||
add dont-require-permissions=yes name=nas-backup owner=admin policy=\ |
||||
ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ |
||||
\r\ |
||||
\n:global nasFtpHost \"10.100.1.10\"\r\ |
||||
\n:global nasFtpUser \"admin\"\r\ |
||||
\n:global nasFtpPass \"REDACTED_SEE_NAS_VAULT\"\r\ |
||||
\n:global nasFtpPath \"mainpve/mikrotik\"\r\ |
||||
\n:local bname \"nas-latest\"\r\ |
||||
\n:log info \"NAS backup: mulai\"\r\ |
||||
\n/system backup save name=\$bname\r\ |
||||
\n/export file=\$bname\r\ |
||||
\n:delay 2s\r\ |
||||
\n/tool fetch address=\$nasFtpHost mode=ftp user=\$nasFtpUser password=\$n\ |
||||
asFtpPass src-path=(\$bname . \".backup\") dst-path=(\$nasFtpPath . \"/\" \ |
||||
. \$bname . \".backup\") upload=yes\r\ |
||||
\n/tool fetch address=\$nasFtpHost mode=ftp user=\$nasFtpUser password=\$n\ |
||||
asFtpPass src-path=(\$bname . \".rsc\") dst-path=(\$nasFtpPath . \"/\" . \ |
||||
\$bname . \".rsc\") upload=yes\r\ |
||||
\n/file remove (\$bname . \".backup\")\r\ |
||||
\n/file remove (\$bname . \".rsc\")\r\ |
||||
\n:log info \"NAS backup: selesai\"\r\ |
||||
\n" |
||||
/tool netwatch |
||||
add comment="hybrid monitor ISP1" down-script=hybrid-set-mode-isp1-down host=\ |
||||
117.102.73.97 interval=10s timeout=3s type=simple up-script=\ |
||||
hybrid-sync-mode |
||||
add comment="hybrid monitor ISP2" down-script=hybrid-set-mode-isp2-down host=\ |
||||
192.168.1.1 interval=10s timeout=3s type=simple up-script=\ |
||||
hybrid-sync-mode |
||||
@ -0,0 +1,3 @@
@@ -0,0 +1,3 @@
|
||||
# ADR Template |
||||
|
||||
Salin untuk keputusan baru. Contoh: [ADR-0001-hybrid-dual-wan.md](./ADR-0001-hybrid-dual-wan.md). |
||||
@ -0,0 +1,36 @@
@@ -0,0 +1,36 @@
|
||||
# ADR-0001: Hybrid Dual-WAN (failover + PCC office) |
||||
|
||||
| Field | Value | |
||||
|-------|-------| |
||||
| Status | Accepted (live) | |
||||
| Date | 2026-06-13 (verified 2026-07-06) | |
||||
|
||||
--- |
||||
|
||||
## Context |
||||
|
||||
Dua ISP: Biznet (ether1, IP publik statik) dan IDBiz (sfp-sfpplus1, DHCP). Butuh internet user kantor tetap jalan saat satu ISP down. |
||||
|
||||
--- |
||||
|
||||
## Decision |
||||
|
||||
- **Failover** default route main: ISP1 `check-gateway=ping`, backup ISP2 |
||||
- **Hybrid PCC** untuk office: scheduler `hybrid-sync-mode` + netwatch ISP1/ISP2 |
||||
- Routing tables `KE ISP 1` / `KE ISP 2` + mangle marks |
||||
- Script deploy: `server-connection/scripts/apply-hybrid-mikrotik.ps1` |
||||
|
||||
--- |
||||
|
||||
## Consequences |
||||
|
||||
**Positif:** Resiliensi ISP; office load-balance saat both up |
||||
|
||||
**Negatif:** Kompleksitas troubleshooting; perubahan salah bisa putus internet seluruh kantor |
||||
|
||||
--- |
||||
|
||||
## References |
||||
|
||||
- `server-connection/server/existing-network-geonet.txt` |
||||
- `backups/mikrotik-export-2026-07-06.rsc` |
||||
@ -0,0 +1,38 @@
@@ -0,0 +1,38 @@
|
||||
# AI Session Summary |
||||
|
||||
```yaml |
||||
session: 2026-07-06-mikrotik-bootstrap-audit |
||||
project: Mikrotik/ |
||||
version: 0.1.0 |
||||
status: ready |
||||
next: Verifikasi NAT mail gisportal.id vs Mailcow .28 setelah perubahan DNS |
||||
agent: Cursor |
||||
``` |
||||
|
||||
## TL;DR |
||||
|
||||
- Bootstrap repo `Mikrotik/` + **audit live** `10.100.1.1` (RouterOS 7.5, uptime ~1d) |
||||
- Mode jaringan: **hybrid dual-WAN** (ISP1 Biznet + ISP2 IDBiz) + failover `check-gateway=ping` |
||||
- Backup `/export compact` → `backups/mikrotik-export-2026-07-06.rsc` (NAS FTP pass **diredaksi**) |
||||
- Mail publik `117.102.73.102` → NAT ke Mailcow `10.100.1.28` (:25/:587/:993/:465) |
||||
- Chat sebelumnya: user tanya riwayat MikroTik — ada di `server-connection/`, belum di chat Cursor |
||||
|
||||
## Lanjut dari sini |
||||
|
||||
1. Dokumentasi NAT mail selaras Mailcow `gisportal.id` — [notes/nat-mail-gisportal.md](./notes/nat-mail-gisportal.md) |
||||
2. Sebelum ubah routing: backup baru + append `version.md` |
||||
3. Pertimbangkan nonaktifkan PPTP (legacy) |
||||
|
||||
## Jangan |
||||
|
||||
- Commit `nasFtpPass` atau PPP password plaintext |
||||
- Edit SPF/DKIM di MikroTik |
||||
- Import `.rsc` ke production tanpa maintenance window |
||||
|
||||
## Konteks chat (disimpan) |
||||
|
||||
| Topik | Ringkasan | |
||||
|-------|-----------| |
||||
| Riwayat MikroTik di chat | Belum troubleshoot eksplisit di Cursor; infra ada di `server-connection/server/` | |
||||
| Mailcow gisportal | MX langsung `.102`; NAT port email ke `.28` — DNS SPF di Master Web | |
||||
| SSH gagal tanpa key | `Permission denied` — wajib `id_rsa_mikrotik` | |
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue