sumarsono.com
Take it with a grain of salt
Zola
2024-02-22T08:59:00+07:00
https://www.sumarsono.com/atom.xml
Rofi KDE Global Shortcut
2024-02-22T08:59:00+07:00
2024-02-22T08:59:00+07:00
Unknown
https://www.sumarsono.com/rofi-kde-global-shortcut/
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">nano /home/sumar/.local/bin/rofi-launch.sh
</span></code></pre>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="font-style:italic;color:#928374;">#!/bin/bash
</span><span style="color:#9d0006;">export </span><span style="color:#282828;">LC_ALL</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">"C"
</span><span style="color:#282828;">rofi -combi-modi window,drun,ssh -show combi </span><span style="color:#8f3f71;">2</span><span style="color:#b23c15;">>&</span><span style="color:#8f3f71;">1 </span><span style="color:#b23c15;">| </span><span style="color:#282828;">tee /tmp/rofi-run.log
</span><span style="color:#b57614;">exit</span><span style="color:#282828;"> 0
</span></code></pre>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">chmod +x /home/sumar/.local/bin/rofi-launch.sh
</span></code></pre>
<p>KDE System Settings > Shortcuts > Custom Shortcuts:</p>
<ul>
<li>Right Click > New > Global Shortcut > Command/URL</li>
<li>Trigger > Shortcut > press Meta + Space</li>
<li>Command > /home/sumar/.local/bin/rofi-launch.sh</li>
</ul>
Install MySQL v8 on Debian 11
2024-01-24T15:40:00+07:00
2024-01-24T15:40:00+07:00
Unknown
https://www.sumarsono.com/install-mysql-8-on-debian-11/
<p>Ceritanya, aku lagi mencoba memasang <a href="https://hestiacp.com/install.html">HestiaCP</a>. Tapi, ada galat: gagal memasang mysql v8 dengan log:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>Updating currently installed packages, please wait... W: GPG error: http://repo.mysql.com/apt/debian bullseye InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY B7B3B788A8D3785C
</span><span>E: The repository 'http://repo.mysql.com/apt/debian bullseye InRelease' is not signed.
</span></code></pre>
<p>Saat-nya mengeluarkan jurus Google-fu dan ketemu solusi <a href="https://askubuntu.com/a/1497141">StackOverFlow</a>:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys B7B3B788A8D3785C && rm /etc/apt/keyrings/mysql.gpg && gpg --output /etc/apt/keyrings/mysql.gpg --export B7B3B788A8D3785C
</span></code></pre>
<p>Sesuaikan dengan apt source list yang dibuat installer HestiaCP menjadi:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys B7B3B788A8D3785C;
</span><span>rm /usr/share/keyrings/mysql-keyring.gpg;
</span><span>gpg --output /usr/share/keyrings/mysql-keyring.gpg --export B7B3B788A8D3785C;
</span><span>
</span></code></pre>
<p>Test pakai apt update. All good!</p>
<p>PR been submitted to <a href="https://github.com/hestiacp/hestiacp/pull/4259">upstream</a></p>
Deploy Vaultwarden and Postgres on Fly.io
2024-01-10T11:30:00+07:00
2024-01-10T11:30:00+07:00
Unknown
https://www.sumarsono.com/deploy-vaultwarden-and-postgres-on-fly-io/
<p>fly.io per January 10, 2024 masih memiliki free allowance untuk setiap verified user:</p>
<ul>
<li>Up to 3 shared-cpu-1x 256mb VMs</li>
<li>3GB persistent volume storage (total)</li>
<li>160GB outbound data transfer </li>
</ul>
<p>source: https://fly.io/docs/about/pricing/#free-allowances</p>
<p>Free allowance tersebut bisa kita manfaatkan untuk deploy aplikasi kecil, misalnya personal Vaultwarden instance dengan konfigurasi:</p>
<ul>
<li>1 app instance tanpa persistent volume storage.</li>
<li>2 postgres instances dengan persistent volume storage masing-masing 1GB.</li>
</ul>
<blockquote>
<p>Hey, Vaultwarden bisa pakai sqlite, kenapa repot-repot pakai Postgres? Tentu saja for the sake of learning, it's fun.</p>
</blockquote>
<h2 id="install-flyctl-dan-login">Install flyctl dan login</h2>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>curl -L https://fly.io/install.sh | sh
</span><span>fly auth login
</span></code></pre>
<h2 id="deploy-postgres-on-fly-io">Deploy postgres on fly.io</h2>
<p>Pertama, bikin instance postgres-nya, ikuti wizardnya, pilih yang development dengan spesifikasi shared instance 1vCPU 256MB RAM, dan storage 1GB</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>mkdir flyio-postgres
</span><span>cd flyio-postgres/
</span><span>fly postgres create
</span></code></pre>
<p>Kedua, kita scale jadi 2 instances. Buat jaga-jaga kalau butuh failover</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>
</span><span>fly machine list
</span><span>fly machine clone <id dari machine list> --region sin --app my-vaultwarden-db
</span></code></pre>
<p>Nanti hasilnya ada 2 instances posgres: 1 read-write dan 1 read only.</p>
<p>Test koneksi ke db</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>fly postgres connect --app my-vaultwarden-db
</span></code></pre>
<p>Simpan config fly.toml buat dipelajari</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>fly config save --app my-vaultwarden-db
</span></code></pre>
<h2 id="deploy-vaultwarden-on-fly-io">Deploy Vaultwarden on fly.io</h2>
<p>Pertama, init app tanpa deploy, karena kita akan siapkan confignya</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>cd ..
</span><span>mkdir flyio-vaultwarden
</span><span>cd flyio-vaultwarden
</span><span>flyctl launch --no-deploy
</span></code></pre>
<p>Kedua, edit fly.toml dan tambahkan Env var yang dibutuhkan</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>vim fly.toml
</span></code></pre>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>app = "my-vaultwarden"
</span><span>primary_region = "sin"
</span><span>swap_size_mb = 512
</span><span>
</span><span>[build]
</span><span> image = "vaultwarden/server:latest"
</span><span>
</span><span>[env]
</span><span> ROCKET_PORT = 8080
</span><span> DOMAIN = "https://my-vaultwarden.fly.dev"
</span><span> LOG_LEVEL = "error"
</span><span> ORG_EVENTS_ENABLED = true
</span><span> EVENTS_DAYS_RETAIN = 7
</span><span>
</span><span> IP_HEADER = "Fly-Client-IP"
</span><span>
</span><span> SIGNUPS_ALLOWED = false
</span><span> SIGNUPS_VERIFY = true
</span><span> SIGNUPS_DOMAINS_WHITELIST = "yourpersonaldomain.tld"
</span><span>
</span><span> # https://github.com/dani-garcia/vaultwarden/wiki/SMTP-Configuration
</span><span> SMTP_HOST = "your-config"
</span><span> SMTP_FROM = "your-config"
</span><span> SMTP_FROM_NAME = "your-config"
</span><span> SMTP_SECURITY = "starttls"
</span><span> SMTP_PORT = 587
</span><span>
</span><span> # https://github.com/dani-garcia/vaultwarden/wiki/Enabling-Mobile-Client-push-notification
</span><span> PUSH_ENABLED = true
</span><span> PUSH_INSTALLATION_ID = "your-config"
</span><span>
</span><span> # Following environment variables are saved in fly secret
</span><span> # ADMIN_TOKEN
</span><span> # PUSH_INSTALLATION_KEY
</span><span> # SMTP_PASSWORD
</span><span> # SMTP_USERNAME
</span><span> # DATABASE_URL
</span><span> # DATABASE_URL was saved in fly secret automaticaly by fly postgres attach
</span><span>
</span><span>
</span><span>[http_service]
</span><span> internal_port = 8080
</span><span> force_https = true
</span><span> auto_stop_machines = true
</span><span> auto_start_machines = true
</span><span> min_machines_running = 0
</span><span> processes = ["app"]
</span><span>
</span><span>[[vm]]
</span><span> cpu_kind = "shared"
</span><span> cpus = 1
</span><span> memory_mb = 256
</span></code></pre>
<p>Ketiga, siapkan secrets untuk environment variable yang sensitif. </p>
<p>Generate secure admin token terlebih dahulu, token ini dipakai untuk login ke halaman admin Vaultwarden:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>echo -n "your-strong-pass" | argon2 "$(openssl rand -base64 32)" -e -id -k 65540 -t 3 -p 4
</span></code></pre>
<p>Simpan secure admin token tersebut ke fly.io secrets</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>fly secrets set --app my-vaultwarden ADMIN_TOKEN='hasil-generate-tadi'
</span></code></pre>
<p>Simpan kredensial SMTP ke fly.io secrets</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>fly secrets set --app my-vaultwarden SMTP_PASSWORD='your-smtp-passwd'
</span><span>fly secrets set --app my-vaultwarden SMTP_USERNAME='your-smtp-username'
</span></code></pre>
<p>Simpan PUSH_INSTALLATION_KEY dari https://github.com/dani-garcia/vaultwarden/wiki/Enabling-Mobile-Client-push-notification</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>fly secrets set --app my-vaultwarden PUSH_INSTALLATION_KEY='push installation key'
</span></code></pre>
<p>Create DATABASE_URL dengan cara attach database ke app vaultwarden</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>fly postgres attach --app my-vaultwarden my-vaultwarden-db
</span></code></pre>
<p>command tersebut akan otomatis membuat secrets bernama DATABASE_URL</p>
<p>List semua secrets, pastikan tidak ada yang terlewat:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>fly secrets list
</span></code></pre>
<p>Deploy my-vaultwarden app</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>fly deploy --ha=false
</span></code></pre>
<blockquote>
<p><code>--ha=false</code> ini penting supaya create 1 instance saja, by default fly.io akan membuat 2 instances app. Kita bikin 1 saja supaya tetap gratis.</p>
</blockquote>
<p>Selesai, vaultwarden bisa diakses pakai https://app-name.fly.dev</p>
My Daily Apps In 2023
2023-12-29T11:00:00+07:00
2023-12-29T11:00:00+07:00
Unknown
https://www.sumarsono.com/my-daily-apps-in-2023/
<p>Sehari-hari aku pakai laptop dengan sistem operasi PopOS!, salah satu varian distribusi linux. Berikut ini adalah aplikasi favorit yang setiap hari aku pakai di tahun 2023:</p>
<ul>
<li><a href="https://www.mozilla.org/en-US/firefox/new/">Mozilla Firefox</a>
<ul>
<li>Satu-satunya browser dengan fitur Container, belum ada browser lain yang bisa menggantikan.</li>
</ul>
</li>
<li><a href="https://code.visualstudio.com/">VSCode</a>
<ul>
<li>Defacto IDE yang dipakai oleh semua anggota tim. Dengan berbagai ekstensi yang berguna.</li>
</ul>
</li>
<li><a href="https://alacritty.org/">Alacrity Terminal Emulator</a>
<ul>
<li>Kombo dengan tmux dengan plugin resurrect dan continuum, enak sekali untuk save/restore session. Sekalian jadi wadah untuk aku belajar pakai neovim.</li>
</ul>
</li>
<li><a href="https://keepassxc.org/">KeePassXC</a>
<ul>
<li>Aku pakai untuk menyimpan semua SSH keys, jadi gak ada private key di $HOME/.ssh/ karena khawatir ada node modules yang nakal. </li>
</ul>
</li>
<li><a href="https://obsidian.md/">Obsidian</a>
<ul>
<li>Personal knowledge base and note-taking software yang sangat cocok untukku.</li>
</ul>
</li>
<li><a href="https://heynote.com/">Heynote</a>
<ul>
<li>Dedicated scratchpad yang sangat berguna.</li>
</ul>
</li>
<li><a href="https://cryptomator.org/">Cryptomator</a>
<ul>
<li>Aku encrypt file-file ku sebelum upload ke Cloud Storage.</li>
</ul>
</li>
</ul>
Tmux Resurrect Workaround for Nvim App Image
2023-11-10T08:30:00+07:00
2023-11-10T08:30:00+07:00
Unknown
https://www.sumarsono.com/tmux-resurrect-nvim-app-image/
<p>We will use simple go to wrap the nvim.appimage</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>mkdir $HOME/opt/nvim
</span><span>cd $HOME/opt/nvim
</span><span>wget https://github.com/neovim/neovim/releases/download/v0.9.4/nvim.appimage
</span><span>chmod +x nvim.appimage
</span><span>ln -s $(realpath nvim.appimage) /usr/local/bin/nvim.appimage
</span></code></pre>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>cat <<-'EOF'> nvim.go
</span><span>package main
</span><span>
</span><span>import (
</span><span> "os"
</span><span> "os/exec"
</span><span> "syscall"
</span><span>)
</span><span>
</span><span>func main() {
</span><span> cmd := exec.Command("nvim.appimage", os.Args[1:]...)
</span><span>
</span><span> cmd.Stdin = os.Stdin
</span><span> cmd.Stdout = os.Stdout
</span><span> cmd.Stderr = os.Stderr
</span><span>
</span><span> err := cmd.Run()
</span><span> if err != nil {
</span><span> if exitError, ok := err.(*exec.ExitError); ok {
</span><span> waitStatus := exitError.Sys().(syscall.WaitStatus)
</span><span> os.Exit(waitStatus.ExitStatus())
</span><span> } else {
</span><span> os.Exit(1)
</span><span> }
</span><span> }
</span><span>}
</span><span>EOF
</span><span>
</span><span>go build nvim.go
</span><span>ln -s $(realpath nvim) /usr/local/bin/nvim
</span></code></pre>
<p>Now, following tmux resurrect config will work:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span># for vim
</span><span>set -g @resurrect-strategy-vim 'session'
</span><span># for neovim
</span><span>set -g @resurrect-strategy-nvim 'session'
</span></code></pre>
<p>Thanks</p>
Mempercepat Perintah find -exec
2023-08-03T17:00:00+07:00
2023-08-03T17:00:00+07:00
Unknown
https://www.sumarsono.com/speedup-find-exec/
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>> time find . -type f -exec ls -lah {} \;
</span><span>
</span><span>real 0m21.421s
</span><span>user 0m12.262s
</span><span>sys 0m8.926s
</span><span>
</span></code></pre>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>> time find . -type f -exec ls -lah {} +
</span><span>
</span><span>real 0m0.268s
</span><span>user 0m0.106s
</span><span>sys 0m0.153s
</span><span>
</span></code></pre>
<p>Hanya dengan mengganti <code>\;</code> dengan <code>+</code> dapat mempercepat sebesar <strong>79.929104478x</strong></p>
<p>Kok bisa begitu? karena:</p>
<ul>
<li><code>-exec ls -lah {} \;</code> Menjalankan <code>ls -lah</code> untuk setiap file yang ditemukan, satu-satu.</li>
<li><code>-exec ls -lah {} +</code> Mengumpulkan path file yang ditemukan jadi satu baru kemudian menjalankan <code>ls -lah</code> satu kali sekaligus. Tapi ini ada batasannya, daftar path file tidak boleh melebihi batas <em>argument</em> sistem. Kalau di linux batasnya sebesar nilai <code>getconf ARG_MAX</code></li>
</ul>
Podman: CouchDB
2023-07-30T09:30:00+07:00
2023-07-30T09:30:00+07:00
Unknown
https://www.sumarsono.com/podman-couchdb/
<p>Aku menjalankan CouchDB container pakai Podman, couchdb ini akan aku pakai untuk Plugin Obsidian LiveSync.</p>
<p>System Info</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>$ cat /etc/os-release
</span><span>PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
</span><span>NAME="Debian GNU/Linux"
</span><span>VERSION_ID="12"
</span><span>VERSION="12 (bookworm)"
</span><span>VERSION_CODENAME=bookworm
</span><span>ID=debian
</span><span>HOME_URL="https://www.debian.org/"
</span><span>SUPPORT_URL="https://www.debian.org/support"
</span><span>BUG_REPORT_URL="https://bugs.debian.org/"
</span><span>
</span><span>$ podman version
</span><span>Client: Podman Engine
</span><span>Version: 4.3.1
</span><span>API Version: 4.3.1
</span><span>Go Version: go1.19.8
</span><span>Built: Thu Jan 1 00:00:00 1970
</span><span>OS/Arch: linux/amd64
</span></code></pre>
<p>Siapkan working directory</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>$ mkdir -p ~/couchdb/data
</span><span>$ cd ~/couchdb
</span></code></pre>
<p>Siapkan couchdb local config</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>$ nano local.ini
</span><span>[couchdb]
</span><span>single_node=true
</span><span>max_document_size = 50000000
</span><span>
</span><span>[chttpd]
</span><span>require_valid_user = true
</span><span>max_http_request_size = 4294967296
</span><span>enable_cors = true
</span><span>
</span><span>[chttpd_auth]
</span><span>require_valid_user = true
</span><span>authentication_redirect = /_utils/session.html
</span><span>
</span><span>[httpd]
</span><span>WWW-Authenticate = Basic realm="couchdb"
</span><span>bind_address = 0.0.0.0
</span><span>enable_cors = true
</span><span>
</span><span>[cors]
</span><span>origins = app://obsidian.md,capacitor://localhost,http://localhost
</span><span>credentials = true
</span><span>headers = accept, authorization, content-type, origin, referer
</span><span>methods = GET,PUT,POST,HEAD,DELETE
</span><span>max_age = 3600
</span></code></pre>
<p>Jalankan container pakai podman</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>$ podman run --detach --name couchdb \
</span><span> -e COUCHDB_USER=your-basic-auth-user \
</span><span> -e COUCHDB_PASSWORD=your-basic-auth-passwd \
</span><span> -v /home/sumar/couchdb/local.ini:/opt/couchdb/etc/local.ini \
</span><span> -v /home/sumar/couchdb/data:/opt/couchdb/data \
</span><span> -p 192.168.1.155:5984:5984 \
</span><span> couchdb:3
</span></code></pre>
<p>Generate config systemd</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>$ podman generate systemd --new --name couchdb > ~/.config/systemd/user/container-couchdb.service
</span></code></pre>
<p>Enable container-couchdb.service</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>$ systemctl --user daemon-reload
</span><span>$ systemctl --user enable --now container-couchdb.service
</span></code></pre>
<p>Selesai</p>
Vaultwarden Rootless Podman
2023-07-25T20:30:00+07:00
2023-07-25T20:30:00+07:00
Unknown
https://www.sumarsono.com/vaultwarden-rootless-podman/
<p>System Info</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>Public IP Address: 192.227.abc.xyz
</span><span>Private IP Address: 192.168.1.155
</span><span>
</span><span>$ cat /etc/os-release
</span><span>PRETTY_NAME="Debian GNU/Linux 11 (bullseye)"
</span><span>NAME="Debian GNU/Linux"
</span><span>VERSION_ID="11"
</span><span>VERSION="11 (bullseye)"
</span><span>VERSION_CODENAME=bullseye
</span><span>ID=debian
</span><span>HOME_URL="https://www.debian.org/"
</span><span>SUPPORT_URL="https://www.debian.org/support"
</span><span>BUG_REPORT_URL="https://bugs.debian.org/"
</span><span>
</span><span>$ podman version
</span><span>Version: 3.0.1
</span><span>API Version: 3.0.0
</span><span>Go Version: go1.15.15
</span><span>Built: Thu Jan 1 00:00:00 1970
</span><span>OS/Arch: linux/amd64
</span></code></pre>
<p>Prepare working dir and files</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>$ mkdir -p ~/vw
</span><span>$ mkdir -p ~/vw/vaultwarden-data
</span><span>$ mkdir -p ~/vw/caddy-config
</span><span>$ mkdir -p ~/vw/caddy-data
</span><span>$ mkdir -p ~/ssl # do not forget to put your valid ssl here
</span><span>
</span><span>$ cd ~/vw
</span><span>$ cat <<- EOF > ~/vw/Caddyfile
</span><span>(access_log_stdout) {
</span><span> log {
</span><span> output stdout
</span><span> format json
</span><span> }
</span><span>}
</span><span>
</span><span>mysub.domain.tld {
</span><span> tls /ssl/my-cert.pem /ssl/my-key.pem
</span><span> encode zstd gzip
</span><span>
</span><span> reverse_proxy 192.168.1.155:8080
</span><span>
</span><span> import access_log_stdout
</span><span>
</span><span> header {
</span><span> -Server
</span><span> -X-Powered-By
</span><span> X-Robots-Tag none
</span><span> X-XSS-Protection "1; mode=block"
</span><span> X-Frame-Options "SAMEORIGIN"
</span><span> }
</span><span>}
</span><span>
</span><span>EOF
</span><span>
</span><span>$ cat << EOF > ~/vw/.env
</span><span>ROCKET_PORT=8080
</span><span>DOMAIN=https://mysub.domain.tld
</span><span>LOG_LEVEL=error
</span><span>ORG_EVENTS_ENABLED=true
</span><span>EVENTS_DAYS_RETAIN=7
</span><span>
</span><span># because i use cloudflare proxy
</span><span>IP_HEADER=CF-Connecting-IP
</span><span>
</span><span>SIGNUPS_ALLOWED=false
</span><span>SIGNUPS_VERIFY=true
</span><span>SIGNUPS_DOMAINS_WHITELIST=domain.tld
</span><span>
</span><span># https://github.com/dani-garcia/vaultwarden/wiki/Enabling-admin-page#secure-the-admin_token
</span><span>ADMIN_TOKEN=your-admin-token-here
</span><span>
</span><span>SMTP_HOST=your-smtp-host
</span><span>SMTP_FROM=your-smtp-from-address
</span><span>SMTP_FROM_NAME=your-smtp-from-name
</span><span>SMTP_SECURITY=starttls
</span><span>SMTP_PORT=587
</span><span>SMTP_USERNAME=your-smtp-username
</span><span>SMTP_PASSWORD=your-smtp-passwd
</span><span>
</span><span>
</span><span># https://github.com/dani-garcia/vaultwarden/wiki/Enabling-Mobile-Client-push-notification
</span><span>PUSH_ENABLED=true
</span><span>PUSH_INSTALLATION_ID=your-push-id
</span><span>PUSH_INSTALLATION_KEY=your-push-key
</span><span>
</span><span>EOF
</span><span>
</span></code></pre>
<p>Final working dir structure</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>/home/sumar/vw
</span><span>|-- .env
</span><span>|-- Caddyfile
</span><span>|-- caddy-config
</span><span>|-- caddy-data
</span><span>|-- ssl
</span><span>| |-- my-cert.pem
</span><span>| `-- my-key.pem
</span><span>`-- vaultwarden-data
</span></code></pre>
<p>Enable service to run event user not log in</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>$ sudo loginctl enable-linger $(id -u $(whoami))
</span></code></pre>
<p>Set DBUS session address</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>$ echo 'export XDG_RUNTIME_DIR="/run/user/$UID"' | tee -a ~/.profile
</span><span>$ echo 'export DBUS_SESSION_BUS_ADDRESS="unix:path=${XDG_RUNTIME_DIR}/bus"' | tee -a ~/.profile
</span></code></pre>
<p>Allow container to bind port 80 and 443</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>$ echo 'net.ipv4.ip_unprivileged_port_start=80' | sudo tee -a /etc/sysctl.d/99-sysctl.conf
</span><span>
</span><span>$ sudo sysctl -p
</span></code></pre>
<p>Run vaultwarden container</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>podman run --detach --name vaultwarden --publish 192.168.1.155:8080:8080 --env-file=/home/sumar/vw/.env --volume /home/sumar/vw/vaultwarden-data/:/data/:Z vaultwarden/server:latest
</span></code></pre>
<p>Run caddy container</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>podman run --detach --name caddy --publish 192.227.abc.xyz:80:80 --publish 192.227.abc.xyz:443:443 --volume /home/sumar/vw/Caddyfile:/etc/caddy/Caddyfile:Z --volume /home/sumar/vw/ssl:/ssl:Z --volume /home/sumar/vw/caddy-data:/data:Z --volume /home/sumar/vw/caddy-config:/config:Z caddy:2-alpine
</span></code></pre>
<p>Generate systemd service</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>$ podman generate systemd --new --name vaultwarden > container-vaultwarden.service
</span><span>$ podman generate systemd --new --name caddy > container-caddy.service
</span><span>
</span><span>$ mkdir -p ~/.config/systemd/user/
</span><span>$ cp container-vaultwarden.service ~/.config/systemd/user/
</span><span>$ cp container-caddy.service ~/.config/systemd/user/
</span></code></pre>
<p>Start and enable systemd service</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>$ systemctl --user daemon-reload
</span><span>$ systemctl --user enable --now container-vaultwarden.service
</span><span>$ systemctl --user enable --now container-caddy.service
</span></code></pre>
<p>Important, do not forget to Setup firewall, bisa ambil contoh:
<a href="https://www.sumarsono.com/ufw-allow-http-https-from-cloudflare/">UFW Allow HTTP HTTPS From Cloudflare IP Address</a></p>
<p>Note:
Kenapa tidak pakai podman network?
krn buggy rootless podman network sering error joining network namespace for container.</p>
UFW Allow HTTP HTTPS From Cloudflare IP Address
2023-07-25T12:10:00+07:00
2023-07-25T12:10:00+07:00
Unknown
https://www.sumarsono.com/ufw-allow-http-https-from-cloudflare/
<p>Install ufw</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>apt install ufw
</span></code></pre>
<p>Deny all incoming</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>ufw default deny incoming
</span></code></pre>
<p>Allow all outgoing</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>ufw default allow outgoing
</span></code></pre>
<p>Allow HTTP/HTTPS from Cloudflare IPv4 and IPv6</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>for i in $(curl https://www.cloudflare.com/ips-v4); do sudo ufw allow from $i to any port 80,443 proto tcp; done
</span><span>
</span><span>for i in $(curl https://www.cloudflare.com/ips-v6); do sudo ufw allow from $i to any port 80,443 proto tcp; done
</span></code></pre>
<p>Enable UFW</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>ufw enable
</span></code></pre>
<p>Check status</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>ufw status verbose
</span><span>
</span><span>Status: active
</span><span>Logging: on (low)
</span><span>Default: deny (incoming), allow (outgoing), disabled (routed)
</span><span>New profiles: skip
</span><span>
</span><span>To Action From
</span><span>-- ------ ----
</span><span>80,443/tcp ALLOW IN 173.245.48.0/20
</span><span>80,443/tcp ALLOW IN 103.21.244.0/22
</span><span>80,443/tcp ALLOW IN 103.22.200.0/22
</span><span>80,443/tcp ALLOW IN 103.31.4.0/22
</span><span>80,443/tcp ALLOW IN 141.101.64.0/18
</span><span>80,443/tcp ALLOW IN 108.162.192.0/18
</span><span>80,443/tcp ALLOW IN 190.93.240.0/20
</span><span>80,443/tcp ALLOW IN 188.114.96.0/20
</span><span>80,443/tcp ALLOW IN 197.234.240.0/22
</span><span>80,443/tcp ALLOW IN 198.41.128.0/17
</span><span>80,443/tcp ALLOW IN 162.158.0.0/15
</span><span>80,443/tcp ALLOW IN 104.16.0.0/13
</span><span>80,443/tcp ALLOW IN 104.24.0.0/14
</span><span>80,443/tcp ALLOW IN 172.64.0.0/13
</span><span>80,443/tcp ALLOW IN 131.0.72.0/22
</span><span>80,443/tcp ALLOW IN 2400:cb00::/32
</span><span>80,443/tcp ALLOW IN 2606:4700::/32
</span><span>80,443/tcp ALLOW IN 2803:f800::/32
</span><span>80,443/tcp ALLOW IN 2405:b500::/32
</span><span>80,443/tcp ALLOW IN 2405:8100::/32
</span><span>80,443/tcp ALLOW IN 2a06:98c0::/29
</span><span>80,443/tcp ALLOW IN 2c0f:f248::/32
</span></code></pre>
Remote Access LXD Server
2023-07-03T17:00:00+07:00
2023-07-03T17:00:00+07:00
Unknown
https://www.sumarsono.com/remote-access-lxd-server/
<p>Diketahui:</p>
<ul>
<li>IP Server LXD: 100.81.128.60/32</li>
<li>IP Laptop: 100.69.46.92</li>
<li>LXC Client version: 5.0.2</li>
<li>LXC Server version: 5.0.2</li>
</ul>
<p>Ditanyakan:
Bagaimana cara untuk mengakses LXD di server dari laptop?</p>
<p>Jawab:
Di Server LXD, tambahkan <code>config trust</code>: </p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>$ lxc config trust add
</span><span>Please provide client name: any-name-you-want
</span><span>Client pop-os certificate add token:
</span><span>you-will-see-generated-token-here
</span></code></pre>
<p>Di Laptop:
tambahkan <code>remote</code>:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>lxc remote add my-lxd-server 100.81.128.60
</span></code></pre>
<p><code>switch</code> ke remote:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>lxc remote switch mesin-canggih
</span><span>lxc info
</span><span>
</span><span># output
</span><span>+----------------+---------+------------------------+-------------------------------------------------+-----------------+-----------+
</span><span>| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
</span><span>+----------------+---------+------------------------+-------------------------------------------------+-----------------+-----------+
</span><span>
</span></code></pre>
<p>Selesai.</p>
Setup Fail2ban to Parse Caddy's Log and Block IP via Cloudflare
2023-06-27T13:37:00+07:00
2023-06-27T13:37:00+07:00
Unknown
https://www.sumarsono.com/setup-fail2ban-to-parse-caddy-log-and-block-ip-via-cloudflare/
<p>Environment yang aku pakai:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>caddy v2.6.4-r3
</span><span>Fail2Ban v1.0.2
</span><span>Alpine Linux v3.18.2
</span></code></pre>
<p>Pertama, install semuanya dan dependensi yang dibutuhkan:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span># apk update
</span><span># apk add caddy fail2ban curl jq
</span></code></pre>
<p>Kemudian config caddy-nya supaya log ke file dan sesuaikan format timestamp-nya, krn fail2ban gak support timestamp default caddy.</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span># cat /etc/caddy/Caddyfile
</span><span>
</span><span>(access_log_file) {
</span><span> log {
</span><span> output file /home/caddy/logs/{args.0}.log {
</span><span> roll_keep 7
</span><span> }
</span><span> format json {
</span><span> # wall will result timestamp: 2006/01/02 15:04:05
</span><span> time_format wall
</span><span> }
</span><span> }
</span><span>}
</span><span>
</span><span>https://whoami.kube.my.id {
</span><span> reverse_proxy {
</span><span> to http://alpine-laravel.lxd:8080
</span><span> transport http
</span><span> }
</span><span>
</span><span> import access_log_file whoami.kube.my.id
</span><span>}
</span><span>
</span></code></pre>
<p>Selanjutnya, bikin fail2ban filter untuk parse caddy access log, disini kita bakal ambil <code>Cf-Connecting-Ip</code> karena serverku berada dibelakang cloudflare.</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span># cat /etc/fail2ban/filter.d/caddy.conf
</span><span>
</span><span>[Definition]
</span><span>prefregex = ^\{"level":"error",<F-CONTENT>.+</F-CONTENT>\}$
</span><span>failregex = ^.*"Cf-Connecting-Ip":\["<HOST>"\].*?"status":(?:401|403|500),.*$
</span><span>ignoreregex =
</span><span>datepattern = %%Y/%%m/%%d %%H:%%M:%%S
</span></code></pre>
<p>Kemudian kita bikin fail2ban action untuk blokir IP via cloudflare</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span># cat /etc/fail2ban/action.d/cloudflare-token.conf
</span><span>
</span><span>[Definition]
</span><span>actionstart =
</span><span>actionstop =
</span><span>actioncheck =
</span><span>
</span><span>actionban = curl -s -X POST "https://api.cloudflare.com/client/v4/zones/<cfzone>/firewall/access_rules/rules" \
</span><span> -H "Authorization: Bearer <cftoken>" \
</span><span> -H "Content-Type: application/json" \
</span><span> --data '{"mode":"block","configuration":{"target":"ip","value":"<ip>"},"notes":"fail2ban"}'
</span><span>
</span><span>actionunban = id=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/<cfzone>/firewall/access_rules/rules" \
</span><span> -H "Authorization: Bearer <cftoken>" \
</span><span> -H "Content-Type:application/json" \
</span><span> | jq '.result[] | select(.configuration.value == "<ip>") | .id' \
</span><span> | tr -d ' ' | tr -d '"'); \
</span><span> if [ -z "$id" ]; then echo "<name>: id for <ip> cannot be found using target <cftarget>"; exit 0; fi; \
</span><span> curl -s -X DELETE "https://api.cloudflare.com/client/v4/zones/<cfzone>/firewall/access_rules/rules/$id" \
</span><span> -H "Authorization: Bearer <cftoken>" \
</span><span> -H "Content-Type:application/json" \
</span><span> --data '{"cascade": "none"}'
</span><span>
</span><span>[Init]
</span><span>cfzone = your-cf-zone-id-here
</span><span>cftoken = yout-cf-token-with-permission-to-edit-firewall-here
</span><span>cftarget = ip
</span><span>cfmode = block
</span><span>
</span><span>[Init?family=inet6]
</span><span>cftarget = ip6
</span></code></pre>
<p>Update fail2ban <code>jail.local</code></p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span># cat /etc/fail2ban/jail.local
</span><span>
</span><span>[caddy]
</span><span>enabled = true
</span><span>port = http,https
</span><span>filter = caddy
</span><span>logpath = /home/caddy/logs/*.log
</span><span>maxretry = 3
</span><span>action = cloudflare-token
</span></code></pre>
<p>Selesai, restart caddy dan fail2ban</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span># service caddy restart
</span><span># service fail2ban restart
</span></code></pre>
<p>Monitor log fail2ban</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span># tail -f /var/log/fail2ban.log
</span><span>
</span><span>2023-06-27 06:30:38,689 fail2ban.server [9962]: INFO Starting Fail2ban v1.0.2
</span><span>2023-06-27 06:30:38,701 fail2ban.server [9962]: INFO Daemon started
</span><span>2023-06-27 06:30:38,702 fail2ban.observer [9962]: INFO Observer start...
</span><span>2023-06-27 06:30:38,715 fail2ban.database [9962]: INFO Connected to fail2ban persistent database '/var/lib/fail2ban/fail2ban.sqlite3'
</span><span>2023-06-27 06:30:38,733 fail2ban.jail [9962]: INFO Creating new jail 'caddy'
</span><span>2023-06-27 06:30:38,734 fail2ban.jail [9962]: INFO Jail 'caddy' uses poller {}
</span><span>2023-06-27 06:30:38,734 fail2ban.jail [9962]: INFO Initiated 'polling' backend
</span><span>2023-06-27 06:30:38,735 fail2ban.datedetector [9962]: INFO date pattern `'%Y/%m/%d %H:%M:%S'`: `Year/Month/Day 24hour:Minute:Second`
</span><span>2023-06-27 06:30:38,735 fail2ban.filter [9962]: INFO maxRetry: 3
</span><span>2023-06-27 06:30:38,736 fail2ban.filter [9962]: INFO findtime: 600
</span><span>2023-06-27 06:30:38,736 fail2ban.actions [9962]: INFO banTime: 600
</span><span>2023-06-27 06:30:38,736 fail2ban.filter [9962]: INFO encoding: UTF-8
</span><span>2023-06-27 06:30:38,737 fail2ban.filter [9962]: INFO Added logfile: '/home/caddy/logs/whoami.kube.my.id.log' (pos = 1911, hash = adc83b19e793491b1c6ea0fd8b46cd9f32e592fc)
</span><span>2023-06-27 06:30:38,744 fail2ban.jail [9962]: INFO Jail 'caddy' started
</span><span>2023-06-27 06:30:56,767 fail2ban.filter [9962]: INFO [caddy] Found 114.10.22.130 - 2023-06-27 06:30:56
</span><span>2023-06-27 06:31:03,374 fail2ban.filter [9962]: INFO [caddy] Found 114.10.22.130 - 2023-06-27 06:31:03
</span><span>2023-06-27 06:31:13,382 fail2ban.filter [9962]: INFO [caddy] Found 114.10.22.130 - 2023-06-27 06:31:12
</span><span>2023-06-27 06:31:13,958 fail2ban.actions [9962]: NOTICE [caddy] Ban 114.10.22.130
</span><span>2023-06-27 06:41:12,539 fail2ban.actions [9962]: NOTICE [caddy] Unban 114.10.22.130
</span></code></pre>
Install Laravel di Alpine Linux Server
2023-06-14T13:00:00+07:00
2023-06-14T13:00:00+07:00
Unknown
https://www.sumarsono.com/install-laravel-di-alpine-linux-server/
<p>Install Package yang Dibutuhkan</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span># apk add vim \
</span><span> zip \
</span><span> unzip \
</span><span> nginx \
</span><span> php-fpm \
</span><span> composer \
</span><span> php-session \
</span><span> php-tokenizer \
</span><span> php-xml \
</span><span> php-dom \
</span><span> php-xmlwriter \
</span><span> php-fileinfo
</span></code></pre>
<p>Install Laravel</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span># cd /var/www/
</span><span># composer create-project laravel/laravel mylaravel
</span><span># chown -R nginx:nginx mylaravel
</span></code></pre>
<p>Ganti User Proses Pool PHP-FPM</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span># vim /etc/php81/php-fpm.d/www.conf
</span><span>;user = nobody
</span><span>;group = nobody
</span><span>user = nginx
</span><span>group = nginx
</span></code></pre>
<h2 id="bikin-vhost-nginx">Bikin Vhost Nginx</h2>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span># cat /etc/nginx/http.d/laravel.conf
</span><span>server {
</span><span> listen 80;
</span><span> listen [::]:80;
</span><span> server_name sub.domain.tld;
</span><span> root /var/www/mylaravel/public;
</span><span>
</span><span> add_header X-Frame-Options "SAMEORIGIN";
</span><span> add_header X-Content-Type-Options "nosniff";
</span><span>
</span><span> index index.php;
</span><span>
</span><span> charset utf-8;
</span><span>
</span><span> location / {
</span><span> try_files $uri $uri/ /index.php?$query_string;
</span><span> }
</span><span>
</span><span> location = /favicon.ico { access_log off; log_not_found off; }
</span><span> location = /robots.txt { access_log off; log_not_found off; }
</span><span>
</span><span> error_page 404 /index.php;
</span><span>
</span><span> location ~ \.php$ {
</span><span> #fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
</span><span> fastcgi_pass 127.0.0.1:9000;
</span><span> fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
</span><span> include fastcgi_params;
</span><span> }
</span><span>
</span><span> location ~ /\.(?!well-known).* {
</span><span> deny all;
</span><span> }
</span><span>}
</span></code></pre>
<p>Restart nginx dan php-fpm</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>/etc/init.d/php-fpm81 restart
</span><span>/etc/init.d/nginx restart
</span></code></pre>
Install Ghost di Alpine Linux Server
2023-06-13T17:00:00+07:00
2023-06-13T17:00:00+07:00
Unknown
https://www.sumarsono.com/install-ghost-di-alpine-linux-server/
<p>Install NodeJS, Nginx, dan Ghost CLI</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span># apk add nodejs npm nginx
</span><span># npm install ghost-cli@latest -g
</span></code></pre>
<p>Bikin user dan direktori untuk Ghost</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span># adduser ghost
</span><span># su - ghost
</span><span>$ mkdir /home/ghost/blog
</span><span>$ mkdir /home/ghost/logs
</span></code></pre>
<p>Install Ghost</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>$ cd /home/ghost/blog
</span><span>$ ghost install
</span><span>$ chown -R ghost:ghost /home/ghost/blog
</span><span>$ exit
</span></code></pre>
<p>Bikin Vhost Nginx</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span># vim /etc/nginx/http.d//ghost.conf
</span><span>server {
</span><span> listen 80;
</span><span> listen [::]:80;
</span><span>
</span><span> server_name blog.kube.my.id;
</span><span>
</span><span> location / {
</span><span> proxy_set_header X-Real-IP $remote_addr;
</span><span> proxy_set_header HOST $http_host;
</span><span> proxy_set_header X-NginX-Proxy true;
</span><span> proxy_pass http://127.0.0.1:2368;
</span><span> proxy_redirect off;
</span><span> }
</span><span>}
</span></code></pre>
<p>Bikin OpenRC Service</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span># vim /etc/init.d/ghost
</span><span>#!/sbin/openrc-run
</span><span>
</span><span>command="/usr/bin/node"
</span><span>directory="/home/ghost/blog"
</span><span>command_args="/usr/local/bin/ghost run"
</span><span>command_background="yes"
</span><span>command_user="ghost:ghost"
</span><span>pidfile="/run/${RC_SVCNAME}.pid"
</span><span>output_log="/home/ghost/logs/${RC_SVCNAME}.log"
</span><span>error_log="/home/ghost/logs/${RC_SVCNAME}.log"
</span><span>
</span><span>depend() {
</span><span> use net
</span><span>}
</span></code></pre>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span># chmod +x /etc/init.d/ghost
</span></code></pre>
<p>Start Service</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span># rc-update add nginx
</span><span># rc-update add ghost
</span><span># service nginx start
</span><span># service ghost start
</span></code></pre>
MacOS Catalina Custom SSH Agent
2023-04-18T07:20:00+07:00
2023-04-18T07:20:00+07:00
Unknown
https://www.sumarsono.com/mac-os-catalina-custom-ssh-agent/
<p>OpenSSH bawaan MacOS Catalina (saat ini) versinya cukup tua dan tidak mendukung ed25519-sk. Salah satu cara agar bisa memakai OpenSSH terbaru adalah dengan menginstall openssh via nix-pkg</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">nix-env -iA nixpkgs.openssh
</span></code></pre>
<p>Command tersebut akan menambahkan binary terbaru untuk <code>ssh-copy-id</code> <code>ssh-keyscan</code> <code>ssh</code> <code>ssh-agent</code> <code>sftp</code> <code>ssh-add</code> <code>scp</code> <code>ssh-keygen</code> <code>sshd</code></p>
<p>Selanjutnya, kita harus membuat konfigurasi LaunchAgent</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">vim ~/Library/LaunchAgents/org.nix.ssh-agent.plist
</span></code></pre>
<pre data-lang="xml" style="background-color:#fcf0ca;color:#282828aa;" class="language-xml "><code class="language-xml" data-lang="xml"><span style="color:#076678;"><?</span><span style="font-weight:bold;color:#407959;">xml </span><span style="color:#407959;">version=</span><span style="color:#79740e;">"1.0" </span><span style="color:#407959;">encoding=</span><span style="color:#79740e;">"UTF-8"</span><span style="color:#076678;">?>
</span><span style="color:#076678;"><!</span><span style="color:#9d0006;">DOCTYPE </span><span style="color:#282828;">plist </span><span style="color:#9d0006;">PUBLIC </span><span style="color:#79740e;">"-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"</span><span style="color:#076678;">>
</span><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">plist </span><span style="color:#407959;">version=</span><span style="color:#79740e;">"1.0"</span><span style="color:#076678;">>
</span><span> </span><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">dict</span><span style="color:#076678;">>
</span><span> </span><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">key</span><span style="color:#076678;">></span><span>Label</span><span style="color:#076678;"></</span><span style="font-weight:bold;color:#407959;">key</span><span style="color:#076678;">>
</span><span> </span><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">string</span><span style="color:#076678;">></span><span>com.homebrew.ssh-agent</span><span style="color:#076678;"></</span><span style="font-weight:bold;color:#407959;">string</span><span style="color:#076678;">>
</span><span> </span><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">key</span><span style="color:#076678;">></span><span>ProgramArguments</span><span style="color:#076678;"></</span><span style="font-weight:bold;color:#407959;">key</span><span style="color:#076678;">>
</span><span> </span><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">array</span><span style="color:#076678;">>
</span><span> </span><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">string</span><span style="color:#076678;">></span><span>/bin/sh</span><span style="color:#076678;"></</span><span style="font-weight:bold;color:#407959;">string</span><span style="color:#076678;">>
</span><span> </span><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">string</span><span style="color:#076678;">></span><span>-c</span><span style="color:#076678;"></</span><span style="font-weight:bold;color:#407959;">string</span><span style="color:#076678;">>
</span><span> </span><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">string</span><span style="color:#076678;">></span><span>rm -f /Users/sumar/.ssh-agent.sock; exec /Users/sumar/.nix-profile/bin/ssh-agent -D -a /Users/sumar/.ssh-agent.sock</span><span style="color:#076678;"></</span><span style="font-weight:bold;color:#407959;">string</span><span style="color:#076678;">>
</span><span> </span><span style="color:#076678;"></</span><span style="font-weight:bold;color:#407959;">array</span><span style="color:#076678;">>
</span><span> </span><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">key</span><span style="color:#076678;">></span><span>RunAtLoad</span><span style="color:#076678;"></</span><span style="font-weight:bold;color:#407959;">key</span><span style="color:#076678;">>
</span><span> </span><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">true</span><span style="color:#076678;">/>
</span><span> </span><span style="color:#076678;"></</span><span style="font-weight:bold;color:#407959;">dict</span><span style="color:#076678;">>
</span><span style="color:#076678;"></</span><span style="font-weight:bold;color:#407959;">plist</span><span style="color:#076678;">>
</span></code></pre>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">launchctl bootstrap gui/$UID ~/Library/LaunchAgents/org.nix.ssh-agent.plist
</span></code></pre>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">launchctl list </span><span style="color:#b23c15;">| </span><span style="color:#282828;">grep ssh
</span></code></pre>
<p>Kemudian export PATH SSH_AUTH_SOCK dari ssh agent tersebut</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#9d0006;">export </span><span style="color:#282828;">SSH_AUTH_SOCK</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">/Users/sumar/.ssh-agent.sock
</span></code></pre>
<p>Dari sini kita bisa juga kombo dengan KeepassXC, Preference > SSH Agent. Kolom SSH_AUTH_SOCK override diisi dengan /Users/sumar/.ssh-agent.sock</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">ssh-add -l
</span></code></pre>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>256 SHA256:<redacted> main_key (ED25519-SK)
</span></code></pre>
Laravel 9.x Multi Stage Docker
2023-01-20T11:05:00+07:00
2023-01-20T11:05:00+07:00
Unknown
https://www.sumarsono.com/laravel-9x-docker-multistage-build/
<p>Goal dari multi stage build ini:</p>
<ul>
<li>untuk cache composer package, hanya composer install ketika ada perubahan di composer.json</li>
<li>untuk cache nodejs package, hanya npm install dan build ketika ada perubahan di package.json</li>
</ul>
<p>Langsung aja, bikin project Laravel pakai composer dan masuk ke dalam direktori projek:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="font-style:italic;color:#928374;"># setup project
</span><span style="color:#282828;">composer create-project laravel/laravel laravel9-example
</span><span>
</span><span style="font-style:italic;color:#928374;"># masuk direktori
</span><span style="color:#b57614;">cd</span><span style="color:#282828;"> laravel9-example
</span><span>
</span><span style="font-style:italic;color:#928374;"># bikin .dockerignore
</span><span style="color:#282828;">touch .dockerignore
</span><span>
</span><span style="font-style:italic;color:#928374;"># bikin Dockerfile
</span><span style="color:#282828;">touch Dockerfile
</span></code></pre>
<p>Kemudian siapkan file-file berikut:
<code>.dockerignore</code></p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>.git/
</span><span>.gitattributes
</span><span>.gitignore
</span><span>.editorconfig
</span><span>.env.example
</span><span>vendor/
</span><span>node_modules/
</span><span>Dockerfile
</span></code></pre>
<p><code>Dockerfile</code></p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span># Install laravel deps
</span><span>FROM composer:2 as vendor
</span><span>RUN mkdir -p /var/www/laravel
</span><span>WORKDIR /var/www/laravel
</span><span>COPY database/ ./database/
</span><span>COPY composer.* ./
</span><span>RUN composer install \
</span><span> --ignore-platform-reqs \
</span><span> --no-interaction \
</span><span> --no-plugins \
</span><span> --no-scripts \
</span><span> --prefer-dist
</span><span>
</span><span># Build asset
</span><span>FROM node:16-alpine as asset
</span><span>RUN mkdir -p /var/www/laravel/public
</span><span>WORKDIR /var/www/laravel
</span><span>COPY package*.json ./
</span><span>RUN npm install
</span><span>COPY vite.config.js ./
</span><span>COPY resources/ resources/
</span><span>RUN npm run build
</span><span>
</span><span>FROM php:8.1-apache
</span><span>ENV APACHE_DOCUMENT_ROOT /var/www/laravel/public
</span><span>RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf
</span><span>RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf
</span><span>
</span><span>RUN mkdir -p /var/www/laravel && chown www-data:www-data /var/www/laravel
</span><span>WORKDIR /var/www/laravel
</span><span>COPY --chown=www-data:www-data . .
</span><span>COPY --chown=www-data:www-data --from=vendor /var/www/laravel/vendor/ ./vendor/
</span><span>COPY --chown=www-data:www-data --from=asset /var/www/laravel/public/build/ ./public/build/
</span><span>USER www-data:www-data
</span></code></pre>
<p>Build container image</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">docker build -t sumarsono/laravel:v9 .
</span></code></pre>
<p>Test run container</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">docker run -d --rm --name laravel9 sumarsono/laravel:v9
</span></code></pre>
Android Reverse Tethering: gnirehtet
2023-01-17T12:40:00+07:00
2023-01-17T12:40:00+07:00
Unknown
https://www.sumarsono.com/android-reverse-tethering/
<p>Intinya adalah share internet dari laptop ke HP Android via USB. Biasanya share internet dari HP Android ke Laptop via USB nah ini dibalik, makanya judulnya reverse tethering.</p>
<h2 id="step-by-step">Step by Step</h2>
<ul>
<li>Di HP Enable usb debug</li>
<li>Di laptop jalankan <code>adb devices</code>, pastikan HP Android terhubung ke laptop via ADB.</li>
<li>Di laptop Download <a href="https://github.com/Genymobile/gnirehtet/releases/download/v2.5/gnirehtet-rust-linux64-v2.5.zip">gnirehtet</a> dari <a href="https://github.com/Genymobile/gnirehtet">halaman github gnirehtet</a> </li>
<li>Di laptop extract file gnirehtet-rust-linux64-v2.5.zip</li>
<li>Di laptop jalankan command:</li>
</ul>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>./gnirehtet run
</span></code></pre>
<ul>
<li>Di HP terima prompt install gnirehtet client.</li>
</ul>
<p>Selesai, sekarang Internet dari laptop sudah di share ke HP Android via USB.</p>
Tahun Baru Wajah Baru: Monorepo, SSG Engine Baru, Theme Baru
2022-12-31T13:40:00+07:00
2022-12-31T13:40:00+07:00
Unknown
https://www.sumarsono.com/tahun-baru-wajah-baru/
<p>Mengawali tahun baru 2023, aku putuskan untuk mencoba hal baru:</p>
<ul>
<li>Mengganti SSG situs ini dari Hugo ke Zola, tidak ada alasan khusus, iseng saja.</li>
<li>Mengganti Tema situs ini.</li>
<li>Memindahkan situs ini dari Netlify ke Cloudflare Pages.</li>
<li>Mencoba monorepo untuk situs ini, alasannya karena biasa coba-coba SSG (Jekyll, Hugo, Zola, dll). Awalnya setiap SSG aku buatkan branch baru, lama-lama terasa ribet. Untuk menyederhanakan maka aku ubah jadi monorepo. Setiap SSG punya folder sendiri dalam satu branch yang sama. Benefitnya, lebih mudah maintain, <em>reuse static assets</em> jadi mudah.</li>
</ul>
<p>Ngomong-ngomong Cloudflare Pages ini cukup straight forward ketika combine dengan github action. Cukup bikin project di cloudflare page, setup custom domain di cloudflare page, generate token profile cloudflare, bikin github action di github repo dan selesai.</p>
<p>Berikut ini contoh github action untuk deploy ssg zola ke cloudflare pages</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">cat .github/workflows/zola.yml
</span></code></pre>
<pre data-lang="yaml" style="background-color:#fcf0ca;color:#282828aa;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">"Zola: build the website and publish to cloudflare page"
</span><span>
</span><span style="color:#8f3f71;">on</span><span>:
</span><span> </span><span style="font-style:italic;color:#928374;"># detect push event in branch monorepo and change directory zola
</span><span> </span><span style="font-weight:bold;color:#407959;">push</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">branches</span><span>:
</span><span> - </span><span style="color:#79740e;">monorepo
</span><span> </span><span style="font-weight:bold;color:#407959;">paths</span><span>:
</span><span> - </span><span style="color:#79740e;">"zola/**"
</span><span> </span><span style="font-style:italic;color:#928374;"># detect push event in branch monorepo and change directory zola
</span><span> </span><span style="font-weight:bold;color:#407959;">pull_request</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">branches</span><span>:
</span><span> - </span><span style="color:#79740e;">monorepo
</span><span> </span><span style="font-weight:bold;color:#407959;">paths</span><span>:
</span><span> - </span><span style="color:#79740e;">"zola/**"
</span><span>
</span><span> </span><span style="font-style:italic;color:#928374;"># allow to trigger manually via dashboard
</span><span> </span><span style="font-weight:bold;color:#407959;">workflow_dispatch</span><span>:
</span><span>
</span><span style="font-weight:bold;color:#407959;">jobs</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">deploy</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">runs-on</span><span>: </span><span style="color:#79740e;">ubuntu-22.04
</span><span>
</span><span> </span><span style="font-weight:bold;color:#407959;">concurrency</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">group</span><span>: </span><span style="color:#79740e;">${{ github.workflow }}-${{ github.ref }}
</span><span>
</span><span> </span><span style="font-weight:bold;color:#407959;">steps</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">Git checkout and update theme
</span><span> </span><span style="font-weight:bold;color:#407959;">uses</span><span>: </span><span style="color:#79740e;">actions/checkout@v3
</span><span> </span><span style="font-weight:bold;color:#407959;">with</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">submodules</span><span>: </span><span style="color:#8f3f71;">true
</span><span> </span><span style="font-weight:bold;color:#407959;">fetch-depth</span><span>: </span><span style="color:#8f3f71;">0
</span><span>
</span><span> - </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">Install and run zola build
</span><span> </span><span style="font-weight:bold;color:#407959;">run</span><span>: </span><span style="color:#9d0006;">|
</span><span style="color:#79740e;"> sudo snap install --edge zola
</span><span style="color:#79740e;"> cd zola
</span><span style="color:#79740e;"> zola build --base-url https://www.sumarsono.com
</span><span style="color:#79740e;">
</span><span> - </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">Publish to cloudflare pages
</span><span> </span><span style="font-weight:bold;color:#407959;">uses</span><span>: </span><span style="color:#79740e;">cloudflare/wrangler-action@2.0.0
</span><span> </span><span style="font-weight:bold;color:#407959;">with</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">apiToken</span><span>: </span><span style="color:#79740e;">${{ secrets.CLOUDFLARE_API_TOKEN }}
</span><span> </span><span style="font-weight:bold;color:#407959;">accountId</span><span>: </span><span style="color:#79740e;">${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
</span><span> </span><span style="font-weight:bold;color:#407959;">command</span><span>: </span><span style="color:#79740e;">pages publish zola/public --project-name=zola --commit-dirty=true --branch=main
</span></code></pre>
<p>Happy new year 2023!</p>
Lock Sesi Linux Ketika Yubikey Dicabut
2022-11-19T10:23:49+07:00
2022-11-19T10:23:49+07:00
Unknown
https://www.sumarsono.com/lock-sesi-linux-ketika-yubikey-dicabut/
<p>Aku ingin ketika Yubikey dicabut maka sesi langsung terkunci. Di distribusi linux yang aku pakai, PopOS!, caranya cukup mudah.</p>
<p>Pertama, aku tancapkan Yubikey.
Kedua, aku run command</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">udevadm monitor --property
</span></code></pre>
<p>Ketiga, aku cabut Yubikey. Sehingga akan muncul output</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>...
</span><span>...
</span><span>UDEV [791.393502] remove /devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3.3 (usb)
</span><span>ACTION=remove
</span><span>DEVPATH=/devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3.3
</span><span>SUBSYSTEM=usb
</span><span>DEVNAME=/dev/bus/usb/001/010
</span><span>DEVTYPE=usb_device
</span><span>PRODUCT=1050/407/543
</span><span>TYPE=0/0/0
</span><span>BUSNUM=001
</span><span>DEVNUM=010
</span><span>SEQNUM=6408
</span><span>USEC_INITIALIZED=773477778
</span><span>ID_PATH=pci-0000:00:14.0-usb-0:3.3
</span><span>ID_PATH_TAG=pci-0000_00_14_0-usb-0_3_3
</span><span>ID_FOR_SEAT=usb-pci-0000_00_14_0-usb-0_3_3
</span><span>MAJOR=189
</span><span>MINOR=9
</span><span>TAGS=:security-device:seat:uaccess:systemd:
</span><span>CURRENT_TAGS=:seat:
</span></code></pre>
<p>Keempat, aku catat <code>SUBSYSTEM=usb</code>, <code>DEVTYPE=usb_device</code>, <code>PRODUCT=1050/407/543</code>.</p>
<p>Kelima, aku bikin file <code>/etc/udev/rules.d/85-yubikey-screen-lock.rules</code> yang isinya</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>ACTION=="remove", ENV{DEVTYPE}=="usb_device", ENV{SUBSYSTEM}=="usb", ENV{PRODUCT}=="1050/407/*", RUN+="/usr/bin/loginctl lock-sessions"
</span></code></pre>
<p>Keenam, aku reload udevadm</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>udevadm control --reload-rules && udevadm trigger
</span></code></pre>
<p>Terakhir, test. Pasang Yubikey, kemudian cabut Yubikey maka sesi akan terkunci.</p>
Docker Buildx on Manjaro
2022-08-25T11:52:49+07:00
2022-08-25T11:52:49+07:00
Unknown
https://www.sumarsono.com/docker-buildx-on-manjaro/
<p>Catatan kecil ketika aku nyobain docker buildx di Laptop dengan OS Manjaro. Aku mencoba build image untuk arm64 dan amd64. Berikut ini ada langkah yang aku tempuh:</p>
<p>Pertama, aku install qemu-user-static ikutin <a href="https://github.com/multiarch/qemu-user-static">guide ini</a>, ringkasannya begini:</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">$ uname -m
</span><span style="color:#282828;">x86_64
</span><span>
</span><span style="color:#282828;">$ docker run --rm -t arm64v8/ubuntu uname -m
</span><span style="color:#282828;">standard_init_linux.go:211: exec user process caused </span><span style="color:#79740e;">"exec format error"
</span><span>
</span><span style="color:#282828;">$ docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
</span><span>
</span><span style="color:#282828;">$ docker run --rm -t arm64v8/ubuntu uname -m
</span><span style="color:#282828;">aarch64
</span></code></pre>
<p>Selanjutnya, aku bikin <em>builder instance</em></p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">$ docker buildx create --name multiarch --driver docker-container --use
</span><span>
</span><span style="color:#282828;">$ docker buildx inspect --bootstrap
</span><span style="font-style:italic;color:#928374;"># output:
</span><span style="color:#282828;">Name: multiarch
</span><span style="color:#282828;">Driver: docker-container
</span><span>
</span><span style="color:#282828;">Nodes:
</span><span style="color:#282828;">Name: multiarch0
</span><span style="color:#282828;">Endpoint: unix:///var/run/docker.sock
</span><span style="color:#282828;">Status: running
</span><span style="color:#282828;">Platforms: linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/386, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/mips64le, linux/mips64
</span></code></pre>
<p>Terakhir, aku coba build image</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">$ cd projects/personal-blog
</span><span>
</span><span style="font-style:italic;color:#928374;"># Target arm64
</span><span style="color:#282828;">$ docker buildx build --load -t sumarsono/personal-blog:latest-arm64 --platform linux/arm64 .
</span><span>
</span><span style="font-style:italic;color:#928374;"># Target amd64
</span><span style="color:#282828;">$ docker buildx build --load -t sumarsono/personal-blog:latest-amd64 --platform linux/amd64 .
</span></code></pre>
<p>Check hasil build</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">REPOSITORY TAG IMAGE ID CREATED SIZE
</span><span style="color:#282828;">sumarsono/personal-blog latest-amd64 545e2a6a7c65 24 minutes ago 56.1MB
</span><span style="color:#282828;">sumarsono/personal-blog latest-arm64 4c38e55cc0b9 29 minutes ago 54.7MB
</span></code></pre>
<p>Dockerfile yang aku coba:</p>
<pre data-lang="yaml" style="background-color:#fcf0ca;color:#282828aa;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span style="font-style:italic;color:#928374;"># build the website
</span><span style="color:#79740e;">FROM klakegg/hugo:latest-ext AS builder
</span><span style="color:#79740e;">COPY . /site
</span><span style="color:#79740e;">WORKDIR /site
</span><span style="color:#79740e;">RUN hugo --minify
</span><span>
</span><span style="font-style:italic;color:#928374;"># publish the build result
</span><span style="color:#79740e;">FROM caddy:2-alpine AS webserver
</span><span style="color:#79740e;">LABEL maintainer="Sumarsono <admin@sumarsono.com>"
</span><span style="color:#79740e;">COPY --from=builder /site/public /usr/share/caddy
</span></code></pre>
Dockerized Reactjs
2022-05-01T12:33:34+07:00
2022-05-01T12:33:34+07:00
Unknown
https://www.sumarsono.com/dockerized-reactjs/
<h2 id="dockerfile-reactjs">Dockerfile reactjs</h2>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>FROM node:14-alpine AS builder
</span><span>#ENV NODE_ENV production
</span><span>
</span><span>WORKDIR /app
</span><span>COPY package*.json ./
</span><span>RUN npm ci
</span><span>COPY . .
</span><span>RUN npm run build
</span><span>
</span><span>FROM nginx:stable-alpine as production
</span><span>#ENV NODE_ENV production
</span><span>
</span><span>COPY --from=builder /app/build /usr/share/nginx/html
</span><span>COPY nginx.conf /etc/nginx/conf.d/default.conf
</span><span>EXPOSE 80
</span><span>CMD ["nginx", "-g", "daemon off;"]
</span></code></pre>
<h2 id="docker-compose-reactjs">docker-compose reactjs</h2>
<pre data-lang="yaml" style="background-color:#fcf0ca;color:#282828aa;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span style="font-weight:bold;color:#407959;">version</span><span>: </span><span style="color:#79740e;">'3.8'
</span><span>
</span><span style="font-weight:bold;color:#407959;">services</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">myapp</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">deploy</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">mode</span><span>: </span><span style="color:#79740e;">replicated
</span><span> </span><span style="font-weight:bold;color:#407959;">replicas</span><span>: </span><span style="color:#8f3f71;">2
</span><span> </span><span style="font-weight:bold;color:#407959;">image</span><span>: </span><span style="color:#79740e;">registry.domain.tld/sumar/myapp:latest
</span><span> </span><span style="font-weight:bold;color:#407959;">restart</span><span>: </span><span style="color:#79740e;">always
</span><span> </span><span style="font-weight:bold;color:#407959;">networks</span><span>:
</span><span> - </span><span style="color:#79740e;">proxy-network
</span><span>
</span><span style="font-weight:bold;color:#407959;">networks</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">proxy-network</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">external</span><span>: </span><span style="color:#8f3f71;">true
</span></code></pre>
Dockerized Adonisjs
2022-05-01T12:24:43+07:00
2022-05-01T12:24:43+07:00
Unknown
https://www.sumarsono.com/dockerized-adonisjs/
<h2 id="dockerfile-for-production-build">Dockerfile for production build</h2>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>ARG NODE_IMAGE=node:16.13.1-alpine
</span><span>
</span><span>FROM $NODE_IMAGE AS base
</span><span>RUN apk --no-cache add dumb-init
</span><span>RUN mkdir -p /home/node/app && chown node:node /home/node/app
</span><span>WORKDIR /home/node/app
</span><span>USER node
</span><span>RUN mkdir tmp
</span><span>
</span><span>FROM base AS dependencies
</span><span>COPY --chown=node:node ./package*.json ./
</span><span>RUN npm ci
</span><span>COPY --chown=node:node . .
</span><span>
</span><span>FROM dependencies AS build
</span><span>RUN node ace build --production
</span><span>
</span><span>FROM base AS production
</span><span>ENV NODE_ENV=production
</span><span>ENV PORT=3333
</span><span>ENV HOST=0.0.0.0
</span><span>COPY --chown=node:node ./package*.json ./
</span><span>RUN npm ci --production
</span><span>COPY --chown=node:node --from=build /home/node/app/build .
</span><span>EXPOSE $PORT
</span><span>CMD [ "dumb-init", "node", "server.js" ]
</span></code></pre>
<h2 id="dockerfile-for-development-build">Dockerfile for development build</h2>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>ARG NODE_IMAGE=node:16.13.1-alpine
</span><span>
</span><span>FROM $NODE_IMAGE AS base
</span><span>RUN apk --no-cache add dumb-init
</span><span>RUN mkdir -p /home/node/app && chown node:node /home/node/app
</span><span>WORKDIR /home/node/app
</span><span>USER node
</span><span>RUN mkdir tmp
</span><span>
</span><span>FROM base AS dependencies
</span><span>COPY --chown=node:node ./package*.json ./
</span><span>RUN npm ci
</span><span>COPY --chown=node:node . .
</span><span>
</span><span>FROM dependencies AS build
</span><span>RUN node ace build
</span><span>
</span><span>FROM base AS development
</span><span>ENV NODE_ENV=development
</span><span>ENV PORT=3333
</span><span>ENV HOST=0.0.0.0
</span><span>COPY --chown=node:node ./package*.json ./
</span><span>RUN npm ci
</span><span>COPY --chown=node:node --from=build /home/node/app/build .
</span><span>EXPOSE $PORT
</span><span>CMD [ "dumb-init", "node", "server.js" ]
</span></code></pre>
<h2 id="run-image-using-docker-compose">Run image using docker-compose</h2>
<pre data-lang="yaml" style="background-color:#fcf0ca;color:#282828aa;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span style="font-weight:bold;color:#407959;">version</span><span>: </span><span style="color:#79740e;">'3.8'
</span><span>
</span><span style="font-weight:bold;color:#407959;">services</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">myapi</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">deploy</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">mode</span><span>: </span><span style="color:#79740e;">replicated
</span><span> </span><span style="font-weight:bold;color:#407959;">replicas</span><span>: </span><span style="color:#8f3f71;">2
</span><span> </span><span style="font-weight:bold;color:#407959;">image</span><span>: </span><span style="color:#79740e;">registry.domain.tld/sumar/myapi:latest
</span><span> </span><span style="font-weight:bold;color:#407959;">restart</span><span>: </span><span style="color:#79740e;">always
</span><span> </span><span style="font-weight:bold;color:#407959;">environment</span><span>:
</span><span> - </span><span style="color:#79740e;">PORT=
</span><span> - </span><span style="color:#79740e;">HOST=
</span><span> - </span><span style="color:#79740e;">NODE_ENV=
</span><span> - </span><span style="color:#79740e;">APP_KEY=
</span><span> - </span><span style="color:#79740e;">DRIVE_DISK=local
</span><span> - </span><span style="color:#79740e;">DB_CONNECTION=
</span><span> - </span><span style="color:#79740e;">MYSQL_HOST=
</span><span> - </span><span style="color:#79740e;">MYSQL_PORT=
</span><span> - </span><span style="color:#79740e;">MYSQL_USER=
</span><span> - </span><span style="color:#79740e;">MYSQL_PASSWORD=
</span><span> - </span><span style="color:#79740e;">MYSQL_DB_NAME=
</span><span> - </span><span style="color:#79740e;">REDIS_CONNECTION=local
</span><span> - </span><span style="color:#79740e;">REDIS_HOST=
</span><span> - </span><span style="color:#79740e;">REDIS_PORT=
</span><span> - </span><span style="color:#79740e;">REDIS_PASSWORD=
</span><span> </span><span style="font-style:italic;color:#928374;">#volumes:
</span><span> </span><span style="font-style:italic;color:#928374;"># - './uploads:/home/node/app/uploads'
</span><span> </span><span style="font-weight:bold;color:#407959;">networks</span><span>:
</span><span> - </span><span style="color:#79740e;">internal-network
</span><span> - </span><span style="color:#79740e;">proxy-network
</span><span>
</span><span style="font-weight:bold;color:#407959;">networks</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">internal-network</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">external</span><span>: </span><span style="color:#8f3f71;">true
</span><span> </span><span style="font-weight:bold;color:#407959;">proxy-network</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">external</span><span>: </span><span style="color:#8f3f71;">true
</span></code></pre>
Logrotate Supervisor
2022-05-01T12:07:52+07:00
2022-05-01T12:07:52+07:00
Unknown
https://www.sumarsono.com/logrotate-supervisor/
<h2 id="supervisor-example">supervisor example</h2>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">cat /etc/supervisor/conf.d/myapi.conf
</span></code></pre>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>[program:myapi-scheduler]
</span><span>command=docker exec -t my-api-1 node ace scheduler:run
</span><span>stdout_logfile=/var/log/supervisor/%(program_name)s.log
</span><span>stderr_logfile=/var/log/supervisor/%(program_name)s.log
</span><span>autorestart=true
</span><span>autostart=true
</span><span>stdout_logfile_maxbytes=0
</span><span>stdout_logfile_backups=0
</span><span>stderr_logfile_maxbytes=0
</span><span>stderr_logfile_backups=0
</span><span>user=myapi
</span><span>group=myapi
</span></code></pre>
<h2 id="logrotate-example">logrotate example</h2>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">cat /etc/logrotate.d/supervisor-myapi
</span></code></pre>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>/var/log/supervisor/*.log {
</span><span> daily
</span><span> missingok
</span><span> rotate 7
</span><span> compress
</span><span> delaycompress
</span><span> notifempty
</span><span> copytruncate
</span><span>}
</span></code></pre>
<h2 id="result-example">result example</h2>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">ls /var/log/supervisor/
</span></code></pre>
<p>myapi-scheduler.log myapi-scheduler.log.2.gz myapi-scheduler.log.4.gz myapi-scheduler.log.6.gz supervisord.log supervisord.log.2.gz
myapi-scheduler.log.1 myapi-scheduler.log.3.gz myapi-scheduler.log.5.gz myapi-scheduler.log.7.gz supervisord.log.1 supervisord.log.3.gz</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code></code></pre>
Kubernetes Adguardhome
2022-04-21T08:28:29+07:00
2022-04-21T08:28:29+07:00
Unknown
https://www.sumarsono.com/kubernetes-adguardhome/
<p>Menjalankan adguardhome di atas kubernetes v1.23.5 menggunakan YAML manifest. YAML
berikut ini mencakup definisi untuk object PersistentVolumeClaim, Deployment, Service, and Ingress</p>
<p>Setelah selesai deploy, kita bisa pakai service DNS AdguarHome untuk wireguard yang pernah dibuat di artikel sebelumnya: <a href="https://www.sumarsono.com/kubernetes-wireguard-pakai-wg-easy/">Kubernetes Wireguard Pakai Wg Easy</a> dengan cara mengganti DNS di konfirgurasi client.</p>
<pre data-lang="yaml" style="background-color:#fcf0ca;color:#282828aa;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span style="color:#407959;">---
</span><span style="font-weight:bold;color:#407959;">apiVersion</span><span>: </span><span style="color:#79740e;">apps/v1
</span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">Deployment
</span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">adguardhome
</span><span> </span><span style="font-weight:bold;color:#407959;">namespace</span><span>: </span><span style="color:#79740e;">adguardhome
</span><span> </span><span style="font-weight:bold;color:#407959;">labels</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">app</span><span>: </span><span style="color:#79740e;">adguardhome
</span><span style="font-weight:bold;color:#407959;">spec</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">replicas</span><span>: </span><span style="color:#8f3f71;">1
</span><span> </span><span style="font-weight:bold;color:#407959;">strategy</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">type</span><span>: </span><span style="color:#79740e;">RollingUpdate
</span><span> </span><span style="font-weight:bold;color:#407959;">rollingUpdate</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">maxUnavailable</span><span>: </span><span style="color:#8f3f71;">1
</span><span> </span><span style="font-weight:bold;color:#407959;">maxSurge</span><span>: </span><span style="color:#8f3f71;">0
</span><span> </span><span style="font-weight:bold;color:#407959;">selector</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">matchLabels</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">app</span><span>: </span><span style="color:#79740e;">adguardhome
</span><span> </span><span style="font-weight:bold;color:#407959;">template</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">labels</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">app</span><span>: </span><span style="color:#79740e;">adguardhome
</span><span> </span><span style="font-weight:bold;color:#407959;">spec</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">containers</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">adguardhome
</span><span> </span><span style="font-weight:bold;color:#407959;">image</span><span>: </span><span style="color:#79740e;">adguard/adguardhome:latest
</span><span> </span><span style="font-weight:bold;color:#407959;">securityContext</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">privileged</span><span>: </span><span style="color:#8f3f71;">false
</span><span> </span><span style="font-weight:bold;color:#407959;">allowPrivilegeEscalation</span><span>: </span><span style="color:#8f3f71;">false
</span><span> </span><span style="font-weight:bold;color:#407959;">ports</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">containerPort</span><span>: </span><span style="color:#8f3f71;">3000
</span><span> </span><span style="font-weight:bold;color:#407959;">protocol</span><span>: </span><span style="color:#79740e;">TCP
</span><span> - </span><span style="font-weight:bold;color:#407959;">containerPort</span><span>: </span><span style="color:#8f3f71;">53
</span><span> </span><span style="font-weight:bold;color:#407959;">protocol</span><span>: </span><span style="color:#79740e;">UDP
</span><span> </span><span style="font-weight:bold;color:#407959;">resources</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">requests</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">memory</span><span>: </span><span style="color:#79740e;">"128Mi"
</span><span> </span><span style="font-weight:bold;color:#407959;">cpu</span><span>: </span><span style="color:#79740e;">"100m"
</span><span> </span><span style="font-weight:bold;color:#407959;">limits</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">memory</span><span>: </span><span style="color:#79740e;">"256Mi"
</span><span> </span><span style="font-weight:bold;color:#407959;">readinessProbe</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">httpGet</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">path</span><span>: </span><span style="color:#79740e;">/
</span><span> </span><span style="font-weight:bold;color:#407959;">port</span><span>: </span><span style="color:#8f3f71;">3000
</span><span> </span><span style="font-weight:bold;color:#407959;">livenessProbe</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">httpGet</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">path</span><span>: </span><span style="color:#79740e;">/
</span><span> </span><span style="font-weight:bold;color:#407959;">port</span><span>: </span><span style="color:#8f3f71;">3000
</span><span> </span><span style="font-weight:bold;color:#407959;">volumeMounts</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">adguardhome-config
</span><span> </span><span style="font-weight:bold;color:#407959;">mountPath</span><span>: </span><span style="color:#79740e;">/opt/adguardhome/conf
</span><span> - </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">adguardhome-logs
</span><span> </span><span style="font-weight:bold;color:#407959;">mountPath</span><span>: </span><span style="color:#79740e;">/opt/adguardhome/work
</span><span> </span><span style="font-weight:bold;color:#407959;">volumes</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">adguardhome-config
</span><span> </span><span style="font-weight:bold;color:#407959;">persistentVolumeClaim</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">claimName</span><span>: </span><span style="color:#79740e;">adguardhome
</span><span> - </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">adguardhome-logs
</span><span> </span><span style="font-weight:bold;color:#407959;">emptyDir</span><span>: {}
</span><span>
</span><span style="color:#407959;">---
</span><span style="font-style:italic;color:#928374;"># Persistent volume claim to store all AdGuard Home configuration data
</span><span style="font-weight:bold;color:#407959;">apiVersion</span><span>: </span><span style="color:#79740e;">v1
</span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">PersistentVolumeClaim
</span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">adguardhome
</span><span> </span><span style="font-weight:bold;color:#407959;">namespace</span><span>: </span><span style="color:#79740e;">adguardhome
</span><span> </span><span style="font-weight:bold;color:#407959;">labels</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">app</span><span>: </span><span style="color:#79740e;">adguardhome
</span><span style="font-weight:bold;color:#407959;">spec</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">storageClassName</span><span>: </span><span style="color:#79740e;">openebs-data
</span><span> </span><span style="font-weight:bold;color:#407959;">accessModes</span><span>:
</span><span> - </span><span style="color:#79740e;">ReadWriteOnce
</span><span> </span><span style="font-weight:bold;color:#407959;">resources</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">requests</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">storage</span><span>: </span><span style="color:#79740e;">2Gi
</span><span>
</span><span style="color:#407959;">---
</span><span style="font-style:italic;color:#928374;"># Service definition for the AdGuard Home web interface and DNS port
</span><span style="font-weight:bold;color:#407959;">apiVersion</span><span>: </span><span style="color:#79740e;">v1
</span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">Service
</span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">adguardhome
</span><span> </span><span style="font-weight:bold;color:#407959;">namespace</span><span>: </span><span style="color:#79740e;">adguardhome
</span><span> </span><span style="font-weight:bold;color:#407959;">labels</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">app</span><span>: </span><span style="color:#79740e;">adguardhome
</span><span style="font-weight:bold;color:#407959;">spec</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">type</span><span>: </span><span style="color:#79740e;">ClusterIP
</span><span> </span><span style="font-weight:bold;color:#407959;">selector</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">app</span><span>: </span><span style="color:#79740e;">adguardhome
</span><span> </span><span style="font-weight:bold;color:#407959;">ports</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">port</span><span>: </span><span style="color:#8f3f71;">3000
</span><span> </span><span style="font-weight:bold;color:#407959;">targetPort</span><span>: </span><span style="color:#8f3f71;">3000
</span><span> </span><span style="font-weight:bold;color:#407959;">protocol</span><span>: </span><span style="color:#79740e;">TCP
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">adguard-dashboard
</span><span> - </span><span style="font-weight:bold;color:#407959;">port</span><span>: </span><span style="color:#8f3f71;">53
</span><span> </span><span style="font-weight:bold;color:#407959;">targetPort</span><span>: </span><span style="color:#8f3f71;">53
</span><span> </span><span style="font-weight:bold;color:#407959;">protocol</span><span>: </span><span style="color:#79740e;">UDP
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">adguard-dns
</span><span>
</span><span style="color:#407959;">---
</span><span style="font-weight:bold;color:#407959;">apiVersion</span><span>: </span><span style="color:#79740e;">networking.k8s.io/v1
</span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">Ingress
</span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">adguardhome
</span><span> </span><span style="font-weight:bold;color:#407959;">namespace</span><span>: </span><span style="color:#79740e;">adguardhome
</span><span> </span><span style="font-weight:bold;color:#407959;">labels</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">app</span><span>: </span><span style="color:#79740e;">adguardhome
</span><span> </span><span style="font-weight:bold;color:#407959;">annotations</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">cert-manager.io/cluster-issuer</span><span>: </span><span style="color:#79740e;">"production-issuer"
</span><span> </span><span style="font-weight:bold;color:#407959;">nginx.ingress.kubernetes.io/rewrite-target</span><span>: </span><span style="color:#79740e;">/
</span><span>
</span><span style="font-weight:bold;color:#407959;">spec</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">ingressClassName</span><span>: </span><span style="color:#79740e;">nginx
</span><span> </span><span style="font-weight:bold;color:#407959;">rules</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">host</span><span>: </span><span style="color:#79740e;">adguardhome.your-domain.tld
</span><span> </span><span style="font-weight:bold;color:#407959;">http</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">paths</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">path</span><span>: </span><span style="color:#79740e;">/
</span><span> </span><span style="font-weight:bold;color:#407959;">pathType</span><span>: </span><span style="color:#79740e;">Prefix
</span><span> </span><span style="font-weight:bold;color:#407959;">backend</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">service</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">adguardhome
</span><span> </span><span style="font-weight:bold;color:#407959;">port</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">number</span><span>: </span><span style="color:#8f3f71;">3000
</span><span> </span><span style="font-weight:bold;color:#407959;">tls</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">hosts</span><span>:
</span><span> - </span><span style="color:#79740e;">adguardhome.your-domain.tld
</span><span> </span><span style="font-weight:bold;color:#407959;">secretName</span><span>: </span><span style="color:#79740e;">adguardhome.your-domain.tld-cert
</span></code></pre>
<p>Contoh penggunaan untuk peer wireguard, dapatkan cluster ip dari service adguardhome:</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">sumar@lab0:~$ kubectl -n adguardhome get svc
</span><span style="color:#282828;">NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S</span><span>) </span><span style="color:#282828;">AGE
</span><span style="color:#282828;">adguardhome ClusterIP 10.110.161.113 </span><span style="color:#b23c15;"><</span><span style="color:#282828;">none</span><span style="color:#b23c15;">> </span><span style="color:#8f3f71;">3000</span><span style="color:#282828;">/TCP,53/UDP 34m
</span></code></pre>
<p>Masukan cluster ip tsb ke konfigurasi wireguard klien</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>[Interface]
</span><span>PrivateKey = <redacted>
</span><span>Address = 10.8.0.3/24
</span><span># pakai dns adguardhome
</span><span>DNS = 10.110.161.113
</span><span>
</span><span>
</span><span>[Peer]
</span><span>PublicKey = <redacted>
</span><span>PresharedKey = <redacted>
</span><span>AllowedIPs = 0.0.0.0/0
</span><span>PersistentKeepalive = 25
</span><span>Endpoint = <redacted>
</span></code></pre>
Kubernetes Wireguard Pakai Wg Easy
2022-04-20T11:53:49+07:00
2022-04-20T11:53:49+07:00
Unknown
https://www.sumarsono.com/kubernetes-wireguard-pakai-wg-easy/
<p><a href="https://github.com/WeeJeWel/wg-easy">WireGuard Easy</a>, The easiest way to run WireGuard VPN + Web-based Admin UI.</p>
<p>Karena belum ada yang share cara deploy wg-easy ke kubernetes selain pakai helm, maka aku tulis ini. Sekadar catatan bagaimana aku deploy wireguard VPN diatas kubernetes.</p>
<pre data-lang="yaml" style="background-color:#fcf0ca;color:#282828aa;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span style="color:#407959;">---
</span><span style="font-weight:bold;color:#407959;">apiVersion</span><span>: </span><span style="color:#79740e;">v1
</span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">PersistentVolumeClaim
</span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">wg-easy-pvc
</span><span> </span><span style="font-weight:bold;color:#407959;">namespace</span><span>: </span><span style="color:#79740e;">wireguard
</span><span style="font-weight:bold;color:#407959;">spec</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">storageClassName</span><span>: </span><span style="color:#79740e;">openebs-data
</span><span> </span><span style="font-weight:bold;color:#407959;">accessModes</span><span>:
</span><span> - </span><span style="color:#79740e;">ReadWriteOnce
</span><span> </span><span style="font-weight:bold;color:#407959;">resources</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">requests</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">storage</span><span>: </span><span style="color:#79740e;">0.25Gi
</span><span>
</span><span style="color:#407959;">---
</span><span style="font-weight:bold;color:#407959;">apiVersion</span><span>: </span><span style="color:#79740e;">apps/v1
</span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">Deployment
</span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">wg-easy
</span><span> </span><span style="font-weight:bold;color:#407959;">namespace</span><span>: </span><span style="color:#79740e;">wireguard
</span><span> </span><span style="font-weight:bold;color:#407959;">labels</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">app</span><span>: </span><span style="color:#79740e;">wg-easy
</span><span style="font-weight:bold;color:#407959;">spec</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">replicas</span><span>: </span><span style="color:#8f3f71;">1
</span><span> </span><span style="font-weight:bold;color:#407959;">strategy</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">type</span><span>: </span><span style="color:#79740e;">Recreate
</span><span> </span><span style="font-weight:bold;color:#407959;">selector</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">matchLabels</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">app</span><span>: </span><span style="color:#79740e;">wg-easy
</span><span> </span><span style="font-weight:bold;color:#407959;">template</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">labels</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">app</span><span>: </span><span style="color:#79740e;">wg-easy
</span><span> </span><span style="font-weight:bold;color:#407959;">spec</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">restartPolicy</span><span>: </span><span style="color:#79740e;">Always
</span><span> </span><span style="font-weight:bold;color:#407959;">initContainers</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">init
</span><span> </span><span style="font-weight:bold;color:#407959;">image</span><span>: </span><span style="color:#79740e;">busybox:1.32.0
</span><span> </span><span style="font-weight:bold;color:#407959;">command</span><span>:
</span><span> - </span><span style="color:#79740e;">sh
</span><span> - </span><span style="color:#79740e;">-c
</span><span> - </span><span style="color:#79740e;">sysctl -w net.ipv4.ip_forward=1 && sysctl -w net.ipv4.conf.all.forwarding=1
</span><span> </span><span style="font-weight:bold;color:#407959;">securityContext</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">privileged</span><span>: </span><span style="color:#8f3f71;">true
</span><span> </span><span style="font-weight:bold;color:#407959;">capabilities</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">add</span><span>:
</span><span> - </span><span style="color:#79740e;">NET_ADMIN
</span><span> </span><span style="font-weight:bold;color:#407959;">containers</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">wg-easy
</span><span> </span><span style="font-weight:bold;color:#407959;">image</span><span>: </span><span style="color:#79740e;">weejewel/wg-easy
</span><span> </span><span style="font-weight:bold;color:#407959;">securityContext</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">privileged</span><span>: </span><span style="color:#8f3f71;">true
</span><span> </span><span style="font-weight:bold;color:#407959;">capabilities</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">add</span><span>:
</span><span> - </span><span style="color:#79740e;">NET_ADMIN
</span><span> </span><span style="font-weight:bold;color:#407959;">ports</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">containerPort</span><span>: </span><span style="color:#8f3f71;">51820
</span><span> </span><span style="font-weight:bold;color:#407959;">protocol</span><span>: </span><span style="color:#79740e;">UDP
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">wg
</span><span> - </span><span style="font-weight:bold;color:#407959;">containerPort</span><span>: </span><span style="color:#8f3f71;">51821
</span><span> </span><span style="font-weight:bold;color:#407959;">protocol</span><span>: </span><span style="color:#79740e;">TCP
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">wg-dashboard
</span><span> </span><span style="font-weight:bold;color:#407959;">env</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">WG_HOST
</span><span> </span><span style="font-weight:bold;color:#407959;">value</span><span>: </span><span style="color:#79740e;">"sub.domain.tld"
</span><span> - </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">PASSWORD
</span><span> </span><span style="font-weight:bold;color:#407959;">value</span><span>: </span><span style="color:#79740e;">"your-dashboard-password"
</span><span> - </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">WG_DEFAULT_DNS
</span><span> </span><span style="font-weight:bold;color:#407959;">value</span><span>: </span><span style="color:#79740e;">"8.8.8.8"
</span><span> </span><span style="font-style:italic;color:#928374;"># - name: "WG_PORT"
</span><span> </span><span style="font-style:italic;color:#928374;"># value: "51820"
</span><span> </span><span style="font-style:italic;color:#928374;"># - name: "WG_DEFAULT_ADDRESS"
</span><span> </span><span style="font-style:italic;color:#928374;"># value: "10.8.0.x"
</span><span> </span><span style="font-style:italic;color:#928374;"># - name: "WG_MTU"
</span><span> </span><span style="font-style:italic;color:#928374;"># value: "1420"
</span><span> </span><span style="font-style:italic;color:#928374;"># - name: "WG_ALLOWED_IPS"
</span><span> </span><span style="font-style:italic;color:#928374;"># value: "192.168.15.0/24, 10.0.1.0/24"
</span><span> </span><span style="font-weight:bold;color:#407959;">resources</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">requests</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">memory</span><span>: </span><span style="color:#79740e;">"64Mi"
</span><span> </span><span style="font-weight:bold;color:#407959;">cpu</span><span>: </span><span style="color:#79740e;">"150m"
</span><span> </span><span style="font-weight:bold;color:#407959;">limits</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">memory</span><span>: </span><span style="color:#79740e;">"128Mi"
</span><span> </span><span style="font-weight:bold;color:#407959;">volumeMounts</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">wg-easy-data
</span><span> </span><span style="font-weight:bold;color:#407959;">mountPath</span><span>: </span><span style="color:#79740e;">/etc/wireguard
</span><span> </span><span style="font-weight:bold;color:#407959;">volumes</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">wg-easy-data
</span><span> </span><span style="font-weight:bold;color:#407959;">persistentVolumeClaim</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">claimName</span><span>: </span><span style="color:#79740e;">wg-easy-pvc
</span><span>
</span><span style="color:#407959;">---
</span><span style="font-weight:bold;color:#407959;">apiVersion</span><span>: </span><span style="color:#79740e;">v1
</span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">Service
</span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">wg-easy
</span><span> </span><span style="font-weight:bold;color:#407959;">namespace</span><span>: </span><span style="color:#79740e;">wireguard
</span><span> </span><span style="font-weight:bold;color:#407959;">labels</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">app</span><span>: </span><span style="color:#79740e;">wg-easy
</span><span style="font-weight:bold;color:#407959;">spec</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">type</span><span>: </span><span style="color:#79740e;">NodePort
</span><span> </span><span style="font-weight:bold;color:#407959;">selector</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">app</span><span>: </span><span style="color:#79740e;">wg-easy
</span><span> </span><span style="font-weight:bold;color:#407959;">ports</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">port</span><span>: </span><span style="color:#8f3f71;">51820
</span><span> </span><span style="font-weight:bold;color:#407959;">targetPort</span><span>: </span><span style="color:#79740e;">wg
</span><span> </span><span style="font-style:italic;color:#928374;"># expose wireguard UDP port via nodePort
</span><span> </span><span style="font-style:italic;color:#928374;"># When import config to client, you must edit the peer port to 30001
</span><span> </span><span style="font-weight:bold;color:#407959;">nodePort</span><span>: </span><span style="color:#8f3f71;">30001
</span><span> </span><span style="font-weight:bold;color:#407959;">protocol</span><span>: </span><span style="color:#79740e;">UDP
</span><span>
</span><span style="color:#407959;">---
</span><span style="font-weight:bold;color:#407959;">apiVersion</span><span>: </span><span style="color:#79740e;">v1
</span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">Service
</span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">wg-easy-dashboard
</span><span> </span><span style="font-weight:bold;color:#407959;">namespace</span><span>: </span><span style="color:#79740e;">wireguard
</span><span> </span><span style="font-weight:bold;color:#407959;">labels</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">app</span><span>: </span><span style="color:#79740e;">wg-easy
</span><span style="font-weight:bold;color:#407959;">spec</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">selector</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">app</span><span>: </span><span style="color:#79740e;">wg-easy
</span><span> </span><span style="font-weight:bold;color:#407959;">ports</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">port</span><span>: </span><span style="color:#8f3f71;">51821
</span><span> </span><span style="font-weight:bold;color:#407959;">targetPort</span><span>: </span><span style="color:#79740e;">wg-dashboard
</span><span>
</span><span style="color:#407959;">---
</span><span style="font-weight:bold;color:#407959;">apiVersion</span><span>: </span><span style="color:#79740e;">networking.k8s.io/v1
</span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">Ingress
</span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">wg-easy-dashboard
</span><span> </span><span style="font-weight:bold;color:#407959;">annotations</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">nginx.ingress.kubernetes.io/rewrite-target</span><span>: </span><span style="color:#79740e;">/
</span><span> </span><span style="font-weight:bold;color:#407959;">cert-manager.io/cluster-issuer</span><span>: </span><span style="color:#79740e;">"production-issuer"
</span><span>
</span><span style="font-weight:bold;color:#407959;">spec</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">ingressClassName</span><span>: </span><span style="color:#79740e;">nginx
</span><span> </span><span style="font-weight:bold;color:#407959;">rules</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">host</span><span>: </span><span style="color:#79740e;">sub.domain.tld
</span><span> </span><span style="font-weight:bold;color:#407959;">http</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">paths</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">path</span><span>: </span><span style="color:#79740e;">/
</span><span> </span><span style="font-weight:bold;color:#407959;">pathType</span><span>: </span><span style="color:#79740e;">Prefix
</span><span> </span><span style="font-weight:bold;color:#407959;">backend</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">service</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">wg-easy-dashboard
</span><span> </span><span style="font-weight:bold;color:#407959;">port</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">number</span><span>: </span><span style="color:#8f3f71;">51821
</span><span> </span><span style="font-weight:bold;color:#407959;">tls</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">hosts</span><span>:
</span><span> - </span><span style="color:#79740e;">sub.domain.tld
</span><span> </span><span style="font-weight:bold;color:#407959;">secretName</span><span>: </span><span style="color:#79740e;">sub.domain.tld-cert
</span></code></pre>
Nyobain Podman Di Debian 11
2022-04-17T20:27:38+07:00
2022-04-17T20:27:38+07:00
Unknown
https://www.sumarsono.com/nyobain-podman-di-debian-11/
<p>Catatan ketika aku nyobain rootless podman di Debian 11</p>
<h2 id="install-podman">Install Podman</h2>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#b57614;">echo </span><span style="color:#79740e;">"deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/Debian_11/ /" </span><span style="color:#b23c15;">| </span><span style="color:#282828;">sudo tee /etc/apt/sources.list.d/libcontainers.list
</span><span style="color:#282828;">curl -L </span><span style="color:#79740e;">"https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/Debian_11/Release.key" </span><span style="color:#b23c15;">| </span><span style="color:#282828;">sudo apt-key add -
</span><span>
</span><span style="color:#282828;">sudo apt update </span><span style="color:#b23c15;">&& </span><span style="color:#282828;">sudo apt install podman -y
</span></code></pre>
<h2 id="menambahkan-docker-registry-dan-mirror-google">Menambahkan docker registry dan mirror google</h2>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">sudo nano /etc/containers/registries.conf
</span><span>
</span><span style="font-style:italic;color:#928374;"># Tambahkan ini
</span><span style="color:#282828;">unqualified-search-registries = </span><span style="color:#9d0006;">[</span><span style="color:#79740e;">'registry.fedoraproject.org'</span><span style="color:#282828;">, </span><span style="color:#79740e;">'docker.io'</span><span style="color:#9d0006;">]
</span><span>
</span><span style="color:#282828;">[[registry]]
</span><span style="color:#282828;">prefix = </span><span style="color:#79740e;">"docker.io"
</span><span style="color:#282828;">location = </span><span style="color:#79740e;">"docker.io"
</span><span style="color:#282828;">[[registry.mirror]]
</span><span style="color:#282828;">location = </span><span style="color:#79740e;">"mirror.gcr.io"
</span></code></pre>
<h2 id="enable-linger-untuk-user-yang-aku-pakai">Enable linger untuk user yang aku pakai</h2>
<p>Podman ini daemonless, supaya container bisa tetap jalan meskipun sesi user habis maka perlu enable linger kemudian reboot mesin</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">sudo loginctl enable-linger sumar
</span><span style="color:#282828;">sudo systemctl reboot
</span></code></pre>
<h2 id="verifikasi-konfigurasi-podman">Verifikasi konfigurasi podman</h2>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">podman info
</span></code></pre>
<h2 id="nyobain-build-image-dari-dockerfile">Nyobain build image dari Dockerfile</h2>
<p>Isi dari Dockerfile</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>FROM klakegg/hugo:0.93.2-ext-alpine AS builder
</span><span>
</span><span>COPY . /site
</span><span>WORKDIR /site
</span><span>
</span><span>RUN hugo --minify
</span><span>
</span><span>FROM caddy:2-alpine AS webserver
</span><span>LABEL maintainer="Sumarsono <admin@sumarsono.com>"
</span><span>
</span><span>COPY --from=builder /site/public /usr/share/caddy
</span></code></pre>
<p>Build:</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">podman build -t docker.io/sumarsono/mysite:latest .
</span></code></pre>
<h2 id="nyobain-bikin-pod-generate-systemd-service-dan-generate-k8s-pod-manifest">Nyobain bikin pod, generate systemd service, dan generate k8s pod manifest</h2>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">podman network create hugo-net
</span><span style="color:#282828;">podman pod create --name hugo-pod --network hugo-net
</span><span style="color:#282828;">podman create --name sumarsono-com --network hugo-net -p 80 --pod hugo-pod docker.io/sumarsono/mysite:latest
</span><span style="color:#282828;">podman pod start hugo-pod
</span><span style="color:#282828;">podman generate systemd --files --name hugo-pod
</span><span style="color:#282828;">podman generate kube hugo-pod -f hugo-pod.yaml
</span></code></pre>
<h2 id="enable-systemd-service-yang-digenerate">enable systemd service yang digenerate</h2>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">mkdir -p /home/sumar/.config/systemd/user
</span><span style="color:#282828;">systemctl --user daemon-reload
</span><span style="color:#282828;">systemctl --user enable --now pod-hugo-pod.service
</span></code></pre>
<p>Test:</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">sumar@server00:~/podman-hugo$ podman port sumarsono-com
</span><span style="color:#282828;">80/tcp -</span><span style="color:#b23c15;">> </span><span style="color:#8f3f71;">0</span><span style="color:#282828;">.0.0.0:46319
</span><span style="color:#282828;">sumar@server00:~/podman-hugo$ curl -IL 0.0.0.0:46319
</span><span style="color:#282828;">HTTP/1.1 200 OK
</span><span style="color:#282828;">Accept-Ranges: bytes
</span><span style="color:#282828;">Content-Length: 12062
</span><span style="color:#282828;">Content-Type: text/html</span><span style="color:#b23c15;">; </span><span style="color:#282828;">charset</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">utf-8
</span><span style="color:#282828;">Etag: </span><span style="color:#79740e;">"ragq5b9b2"
</span><span style="color:#282828;">Last-Modified: Sun, 17 Apr 2022 02:41:35 GMT
</span><span style="color:#282828;">Server: Caddy
</span><span style="color:#282828;">Date: Sun, 17 Apr 2022 14:21:58 GMT
</span></code></pre>
Acme Dns Docker Compose
2022-03-30T14:29:24+07:00
2022-03-30T14:29:24+07:00
Unknown
https://www.sumarsono.com/acme-dns-docker-compose/
<h2 id="dns-entry-at-cloudflare">DNS entry at Cloudflare</h2>
<table><thead><tr><th>Name</th><th>Type</th><th>Value</th><th>Proxied</th></tr></thead><tbody>
<tr><td>auth.acme-dns</td><td>NS</td><td>ns.acme-dns.sumarsono.com</td><td>no</td></tr>
<tr><td>ns.acme-dns</td><td>A</td><td>my public ip address</td><td>no</td></tr>
</tbody></table>
<h2 id="config-config-cfg">config/config.cfg</h2>
<pre data-lang="toml" style="background-color:#fcf0ca;color:#282828aa;" class="language-toml "><code class="language-toml" data-lang="toml"><span>[</span><span style="color:#407959;">general</span><span>]
</span><span style="font-weight:bold;color:#407959;">debug </span><span>= </span><span style="color:#8f3f71;">false
</span><span style="font-weight:bold;color:#407959;">listen </span><span>= </span><span style="color:#79740e;">"0.0.0.0:53"
</span><span style="font-weight:bold;color:#407959;">protocol </span><span>= </span><span style="color:#79740e;">"both"
</span><span style="font-weight:bold;color:#407959;">domain </span><span>= </span><span style="color:#79740e;">"auth.acme-dns.sumarsono.com"
</span><span style="font-weight:bold;color:#407959;">nsname </span><span>= </span><span style="color:#79740e;">"ns.acme-dns.sumarsono.com"
</span><span style="font-weight:bold;color:#407959;">nsadmin </span><span>= </span><span style="color:#79740e;">"sumarsono.com"
</span><span>
</span><span style="font-style:italic;color:#928374;"># Note
</span><span style="font-style:italic;color:#928374;"># In Cloudflare, I have 2 records:
</span><span>
</span><span style="font-style:italic;color:#928374;"># type name content
</span><span style="font-style:italic;color:#928374;"># NS auth.acme-dns ns.acme-dns.sumarsono.com
</span><span style="font-style:italic;color:#928374;"># A ns.acme-dns my public ip
</span><span>
</span><span style="font-weight:bold;color:#407959;">records </span><span>= [
</span><span> </span><span style="color:#79740e;">"auth.acme-dns.sumarsono.com. A my public ip"</span><span>,
</span><span> </span><span style="color:#79740e;">"ns.acme-dns.sumarsono.com. A my public ip,</span><span style="background-color:#932b1e;color:#282828;">
</span><span> </span><span style="background-color:#932b1e;color:#282828;">"auth.acme-dns.sumarsono.com.</span><span> </span><span style="background-color:#932b1e;color:#282828;">NS</span><span> </span><span style="background-color:#932b1e;color:#282828;">ns.acme-dns.sumarsono.com."</span><span>,
</span><span>]
</span><span>
</span><span>
</span><span>[</span><span style="color:#407959;">database</span><span>]
</span><span style="font-weight:bold;color:#407959;">engine </span><span>= </span><span style="color:#79740e;">"sqlite3"
</span><span style="font-weight:bold;color:#407959;">connection </span><span>= </span><span style="color:#79740e;">"/var/lib/acme-dns/acme-dns.db"
</span><span style="font-style:italic;color:#928374;"># connection = "postgres://user:password@localhost/acmedns_db"
</span><span>
</span><span>[</span><span style="color:#407959;">api</span><span>]
</span><span style="font-weight:bold;color:#407959;">ip </span><span>= </span><span style="color:#79740e;">"0.0.0.0"
</span><span style="font-weight:bold;color:#407959;">disable_registration </span><span>= </span><span style="color:#8f3f71;">false
</span><span style="font-weight:bold;color:#407959;">port </span><span>= </span><span style="color:#79740e;">"80"
</span><span style="font-weight:bold;color:#407959;">tls </span><span>= </span><span style="color:#79740e;">"none"
</span><span style="font-weight:bold;color:#407959;">use_header </span><span>= </span><span style="color:#8f3f71;">true
</span><span style="font-weight:bold;color:#407959;">header_name </span><span>= </span><span style="color:#79740e;">"X-Forwarded-For"
</span><span>
</span><span style="font-weight:bold;color:#407959;">corsorigins </span><span>= [
</span><span> </span><span style="color:#79740e;">"*"
</span><span>]
</span><span>
</span><span>[</span><span style="color:#407959;">logconfig</span><span>]
</span><span style="font-weight:bold;color:#407959;">loglevel </span><span>= </span><span style="color:#79740e;">"debug"
</span><span style="font-weight:bold;color:#407959;">logtype </span><span>= </span><span style="color:#79740e;">"stdout"
</span><span style="font-weight:bold;color:#407959;">logformat </span><span>= </span><span style="color:#79740e;">"json"
</span></code></pre>
<h2 id="docker-compose-yaml">docker-compose.yaml</h2>
<pre data-lang="yaml" style="background-color:#fcf0ca;color:#282828aa;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span style="font-weight:bold;color:#407959;">version</span><span>: </span><span style="color:#79740e;">'3'
</span><span style="font-weight:bold;color:#407959;">services</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">acmedns</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">image</span><span>: </span><span style="color:#79740e;">sumarsono/acme-dns:arm64
</span><span> </span><span style="font-weight:bold;color:#407959;">ports</span><span>:
</span><span> - </span><span style="color:#79740e;">"53:53"
</span><span> - </span><span style="color:#79740e;">"53:53/udp"
</span><span> </span><span style="font-style:italic;color:#928374;"># disabled because
</span><span> </span><span style="font-style:italic;color:#928374;"># we run behind reverse proxy
</span><span> </span><span style="font-style:italic;color:#928374;">#- "80:80"
</span><span> </span><span style="font-style:italic;color:#928374;">#- "443:443"
</span><span> </span><span style="font-weight:bold;color:#407959;">volumes</span><span>:
</span><span> - </span><span style="color:#79740e;">./config:/etc/acme-dns:ro
</span><span> - </span><span style="color:#79740e;">./data:/var/lib/acme-dns
</span><span> </span><span style="font-weight:bold;color:#407959;">networks</span><span>:
</span><span> - </span><span style="color:#79740e;">proxy-network
</span><span style="font-weight:bold;color:#407959;">networks</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">proxy-network</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">external</span><span>: </span><span style="color:#8f3f71;">true
</span></code></pre>
Vaultwarden Caddy Docker Compose
2022-03-29T07:49:21+07:00
2022-03-29T07:49:21+07:00
Unknown
https://www.sumarsono.com/vaultwarden-caddy-docker-compose/
<h2 id="caddy-v2">Caddy v2</h2>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">cat caddy/docker-compose.yaml
</span></code></pre>
<pre data-lang="yaml" style="background-color:#fcf0ca;color:#282828aa;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span style="font-weight:bold;color:#407959;">version</span><span>: </span><span style="color:#79740e;">'3'
</span><span style="font-weight:bold;color:#407959;">services</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">caddy</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">image</span><span>: </span><span style="color:#79740e;">caddy:alpine
</span><span> </span><span style="font-weight:bold;color:#407959;">container_name</span><span>: </span><span style="color:#79740e;">webserver
</span><span> </span><span style="font-weight:bold;color:#407959;">restart</span><span>: </span><span style="color:#79740e;">unless-stopped
</span><span> </span><span style="font-weight:bold;color:#407959;">ports</span><span>:
</span><span> - </span><span style="color:#79740e;">80:80
</span><span> - </span><span style="color:#79740e;">443:443
</span><span> </span><span style="font-weight:bold;color:#407959;">volumes</span><span>:
</span><span> - </span><span style="color:#79740e;">./caddy_data:/data
</span><span> - </span><span style="color:#79740e;">./caddy_config:/config
</span><span> - </span><span style="color:#79740e;">./Caddyfile:/etc/caddy/Caddyfile
</span><span> </span><span style="font-weight:bold;color:#407959;">networks</span><span>:
</span><span> - </span><span style="color:#79740e;">proxy-network
</span><span style="font-weight:bold;color:#407959;">networks</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">proxy-network</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">external</span><span>: </span><span style="color:#8f3f71;">true
</span></code></pre>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">cat caddy/Caddyfile
</span></code></pre>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>{
</span><span> email zerossl@sumarsono.com
</span><span> acme_ca https://acme.zerossl.com/v2/DV90
</span><span> # optional
</span><span> # acme_eab {
</span><span> # key_id your kbid
</span><span> # mac_key your hmac key
</span><span> # }
</span><span>}
</span><span>
</span><span>(security_header) {
</span><span> header {
</span><span> Content-Security-Policy "upgrade-insecure-requests"
</span><span> #Strict-Transport-Security max-age=31536000;
</span><span> X-Content-Type-Options nosniff;
</span><span> X-XSS-Protection "1; mode=block;"
</span><span> X-Robots-Tag none;
</span><span> X-Frame-Options SAMEORIGIN;
</span><span> Referrer-Policy no-referrer-when-downgrade;
</span><span> }
</span><span>}
</span><span>
</span><span>(cors) {
</span><span> @origin{args.0} header Origin {args.0}
</span><span> header @origin{args.0} Access-Control-Allow-Origin "{args.0}"
</span><span> header @origin{args.0} Vary Origin
</span><span>}
</span><span>
</span><span>yoursub.domain.tld {
</span><span> reverse_proxy /notifications/hub bitwarden:3012
</span><span> reverse_proxy bitwarden:80
</span><span> import security_header
</span><span>}
</span></code></pre>
<h2 id="vaultwarden">Vaultwarden</h2>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">cat bitwarden/docker-compose.yaml
</span></code></pre>
<pre data-lang="yaml" style="background-color:#fcf0ca;color:#282828aa;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span style="font-weight:bold;color:#407959;">version</span><span>: </span><span style="color:#79740e;">'3'
</span><span>
</span><span style="font-weight:bold;color:#407959;">services</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">bitwarden</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">image</span><span>: </span><span style="color:#79740e;">vaultwarden/server:latest
</span><span> </span><span style="font-weight:bold;color:#407959;">container_name</span><span>: </span><span style="color:#79740e;">vaultwarden
</span><span> </span><span style="font-weight:bold;color:#407959;">restart</span><span>: </span><span style="color:#79740e;">always
</span><span> </span><span style="font-weight:bold;color:#407959;">environment</span><span>:
</span><span> - </span><span style="color:#79740e;">IP_HEADER=X-Forwarded-For
</span><span> - </span><span style="color:#79740e;">WEBSOCKET_ENABLED=true
</span><span> - </span><span style="color:#79740e;">SIGNUPS_ALLOWED=false
</span><span> - </span><span style="color:#79740e;">DOMAIN=https://yoursub.domain.tld
</span><span> - </span><span style="color:#79740e;">SMTP_HOST=
</span><span> - </span><span style="color:#79740e;">SMTP_FROM=
</span><span> - </span><span style="color:#79740e;">SMTP_PORT=587
</span><span> - </span><span style="color:#79740e;">SMTP_SSL=true
</span><span> - </span><span style="color:#79740e;">SMTP_USERNAME=
</span><span> - </span><span style="color:#79740e;">SMTP_PASSWORD=
</span><span> - </span><span style="color:#79740e;">ADMIN_TOKEN=random_admin_token
</span><span> - </span><span style="color:#79740e;">DATABASE_URL=mysql://db_user:db_passwd@db_host/db_name
</span><span> </span><span style="font-weight:bold;color:#407959;">volumes</span><span>:
</span><span> - </span><span style="color:#79740e;">./data:/data
</span><span> </span><span style="font-weight:bold;color:#407959;">networks</span><span>:
</span><span> - </span><span style="color:#79740e;">internal-network
</span><span> - </span><span style="color:#79740e;">proxy-network
</span><span>
</span><span style="font-weight:bold;color:#407959;">networks</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">internal-network</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">external</span><span>: </span><span style="color:#8f3f71;">true
</span><span> </span><span style="font-weight:bold;color:#407959;">proxy-network</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">external</span><span>: </span><span style="color:#8f3f71;">true
</span></code></pre>
<h2 id="mariadb">MariaDB</h2>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">cat mariadb/docker-compose.yaml
</span></code></pre>
<pre data-lang="yaml" style="background-color:#fcf0ca;color:#282828aa;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span style="font-weight:bold;color:#407959;">version</span><span>: </span><span style="color:#79740e;">'3'
</span><span style="font-weight:bold;color:#407959;">services</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">mariadb</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">image</span><span>: </span><span style="color:#79740e;">mariadb:10.5
</span><span> </span><span style="font-weight:bold;color:#407959;">container_name</span><span>: </span><span style="color:#79740e;">mariadb
</span><span> </span><span style="font-weight:bold;color:#407959;">volumes</span><span>:
</span><span> - </span><span style="color:#79740e;">db_data:/var/lib/mysql
</span><span> </span><span style="font-weight:bold;color:#407959;">restart</span><span>: </span><span style="color:#79740e;">unless-stopped
</span><span> </span><span style="font-weight:bold;color:#407959;">environment</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">MYSQL_ROOT_PASSWORD</span><span>: </span><span style="color:#79740e;">strong_root_passwd
</span><span> </span><span style="font-weight:bold;color:#407959;">MYSQL_DATABASE</span><span>: </span><span style="color:#79740e;">db_name
</span><span> </span><span style="font-weight:bold;color:#407959;">MYSQL_USER</span><span>: </span><span style="color:#79740e;">db_user
</span><span> </span><span style="font-weight:bold;color:#407959;">MYSQL_PASSWORD</span><span>: </span><span style="color:#79740e;">db_passwd
</span><span> </span><span style="font-weight:bold;color:#407959;">volumes</span><span>:
</span><span> - </span><span style="color:#79740e;">'./db/data:/var/lib/mysql'
</span><span> - </span><span style="color:#79740e;">'./db/my.cnf:/etc/mysql/conf.d/my.cnf'
</span><span> - </span><span style="color:#79740e;">'./db/sql:/docker-entrypoint-initdb.d'
</span><span> </span><span style="font-weight:bold;color:#407959;">networks</span><span>:
</span><span> - </span><span style="color:#79740e;">internal-network
</span><span>
</span><span style="font-weight:bold;color:#407959;">networks</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">internal-network</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">external</span><span>: </span><span style="color:#8f3f71;">true
</span></code></pre>
Docker Compose: Traefik Ghost Mysql Docker Compose
2022-02-17T15:03:06+07:00
2022-02-17T15:03:06+07:00
Unknown
https://www.sumarsono.com/traefik-ghost-mysql-docker-compose/
<p>Create internal docker network and public docker network:</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">docker network create internal-network</span><span style="color:#b23c15;">;
</span><span style="color:#282828;">docker network create proxy-network</span><span style="color:#b23c15;">;
</span></code></pre>
<p>Traefik docker-compose.yaml</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">mkdir ~/traefik</span><span style="color:#b23c15;">;
</span><span style="color:#b57614;">cd </span><span style="color:#282828;">~/traefik</span><span style="color:#b23c15;">;
</span><span style="color:#282828;">cat </span><span style="color:#b23c15;"><<</span><span style="color:#9d0006;">yaml </span><span style="color:#b23c15;">></span><span style="color:#282828;"> docker-compose.yaml
</span><span style="color:#282828;">version: "3.8"
</span><span style="color:#282828;">
</span><span style="color:#282828;">services:
</span><span style="color:#282828;"> traefik:
</span><span style="color:#282828;"> image: "traefik:v2.5"
</span><span style="color:#282828;"> container_name: "traefik"
</span><span style="color:#282828;"> restart: unless-stopped
</span><span style="color:#282828;"> command:
</span><span style="color:#282828;"> #- "--log.level=DEBUG"
</span><span style="color:#282828;"> - "--api.insecure=true"
</span><span style="color:#282828;"> - "--providers.docker=true"
</span><span style="color:#282828;"> - "--providers.docker.exposedbydefault=false"
</span><span style="color:#282828;"> - "--entrypoints.web.address=:80"
</span><span style="color:#282828;"> - "--entryPoints.web.forwardedHeaders.insecure"
</span><span style="color:#282828;"> ports:
</span><span style="color:#282828;"> - "80:80"
</span><span style="color:#282828;"> - "8080:8080"
</span><span style="color:#282828;"> volumes:
</span><span style="color:#282828;"> - "/var/run/docker.sock:/var/run/docker.sock:ro"
</span><span style="color:#282828;"> networks:
</span><span style="color:#282828;"> - proxy-network
</span><span style="color:#282828;"> labels:
</span><span style="color:#282828;"> - "traefik.docker.network=proxy-network"
</span><span style="color:#282828;"> deploy:
</span><span style="color:#282828;"> resources:
</span><span style="color:#282828;"> limits:
</span><span style="color:#282828;"> cpus: '0.50'
</span><span style="color:#282828;"> memory: 50M
</span><span style="color:#282828;"> reservations:
</span><span style="color:#282828;"> cpus: '0.25'
</span><span style="color:#282828;"> memory: 20M
</span><span style="color:#282828;">
</span><span style="color:#282828;">networks:
</span><span style="color:#282828;"> proxy-network:
</span><span style="color:#282828;"> external: true
</span><span style="color:#9d0006;">yaml
</span><span>
</span><span style="color:#282828;">docker-compose up -d
</span></code></pre>
<p>MySQL docker-compose.yaml</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">mkdir ~/mysql</span><span style="color:#b23c15;">;
</span><span style="color:#b57614;">cd </span><span style="color:#282828;">~/mysql</span><span style="color:#b23c15;">;
</span><span style="color:#282828;">cat </span><span style="color:#b23c15;"><<</span><span style="color:#9d0006;">yaml </span><span style="color:#b23c15;">></span><span style="color:#282828;"> docker-compose.yaml
</span><span style="color:#282828;">version: '3.8'
</span><span style="color:#282828;">
</span><span style="color:#282828;">services:
</span><span style="color:#282828;"> db-mysql8:
</span><span style="color:#282828;"> container_name: mysql8
</span><span style="color:#282828;"> image: mysql/mysql-server:8.0.28-1.2.7-server
</span><span style="color:#282828;"> command: mysqld --default-authentication-plugin=mysql_native_password --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
</span><span style="color:#282828;"> restart: unless-stopped
</span><span style="color:#282828;"> environment:
</span><span style="color:#282828;"> MYSQL_ROOT_PASSWORD: "yourrootstrongpasswd"
</span><span style="color:#282828;"> MYSQL_DATABASE: "ghost_db"
</span><span style="color:#282828;"> MYSQL_USER: "ghost_user"
</span><span style="color:#282828;"> MYSQL_PASSWORD: "ghost_passwd"
</span><span style="color:#282828;"> MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
</span><span style="color:#282828;"> ports:
</span><span style="color:#282828;"> - '3306:3306'
</span><span style="color:#282828;"> volumes:
</span><span style="color:#282828;"> - './db/data:/var/lib/mysql'
</span><span style="color:#282828;"> - './db/my.cnf:/etc/mysql/conf.d/my.cnf'
</span><span style="color:#282828;"> - './db/sql:/docker-entrypoint-initdb.d'
</span><span style="color:#282828;"> networks:
</span><span style="color:#282828;"> - internal-network
</span><span style="color:#282828;">
</span><span style="color:#282828;">networks:
</span><span style="color:#282828;"> internal-network:
</span><span style="color:#282828;"> external: true
</span><span style="color:#9d0006;">yaml
</span><span>
</span><span style="color:#282828;">docker-compose up -d</span><span style="color:#b23c15;">;
</span></code></pre>
<p>Ghost docker-compose.yaml</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">mkdir ~/ghost</span><span style="color:#b23c15;">;
</span><span style="color:#b57614;">cd </span><span style="color:#282828;">~/ghost</span><span style="color:#b23c15;">;
</span><span style="color:#282828;">cat </span><span style="color:#b23c15;"><<</span><span style="color:#9d0006;">yaml </span><span style="color:#b23c15;">></span><span style="color:#282828;"> docker-compose.yaml
</span><span style="color:#282828;">version: '3.8'
</span><span style="color:#282828;">services:
</span><span style="color:#282828;"> ghost:
</span><span style="color:#282828;"> image: 'ghost:4.32-alpine'
</span><span style="color:#282828;"> container_name: ghost-service
</span><span style="color:#282828;"> volumes:
</span><span style="color:#282828;"> - '/home/sumar/ghost/data:/var/lib/ghost/content'
</span><span style="color:#282828;"> restart: unless-stopped
</span><span style="color:#282828;"> environment:
</span><span style="color:#282828;"> url: http://ghost.domain.com
</span><span style="color:#282828;"> mail__from: noreply-ghost@domain.com
</span><span style="color:#282828;"> mail__transport: SMTP
</span><span style="color:#282828;"> mail__options__host: your-smtp.com
</span><span style="color:#282828;"> mail__options__port: 465
</span><span style="color:#282828;"> mail__options__service: SES
</span><span style="color:#282828;"> mail__options__auth__user: your-smtp-user
</span><span style="color:#282828;"> mail__options__auth__pass: your-smtp-passwd
</span><span style="color:#282828;"> database__client: mysql
</span><span style="color:#282828;"> database__connection__host: db-mysql8
</span><span style="color:#282828;"> database__connection__user: ghost_user
</span><span style="color:#282828;"> database__connection__password: ghost_db
</span><span style="color:#282828;"> database__connection__database: ghost_passwd
</span><span style="color:#282828;"> networks:
</span><span style="color:#282828;"> - proxy-network
</span><span style="color:#282828;"> - internal-network
</span><span style="color:#282828;"> labels:
</span><span style="color:#282828;"> - "traefik.enable=true"
</span><span style="color:#282828;"> - "traefik.docker.network=proxy-network"
</span><span style="color:#282828;"> - "traefik.http.routers.ghost.rule=Host(`ghost.domain.com`)"
</span><span style="color:#282828;"> - "traefik.http.routers.ghost.entrypoints=web"
</span><span style="color:#282828;">
</span><span style="color:#282828;">networks:
</span><span style="color:#282828;"> proxy-network:
</span><span style="color:#282828;"> external: true
</span><span style="color:#282828;"> internal-network:
</span><span style="color:#282828;"> external: true
</span><span style="color:#9d0006;">yaml
</span><span>
</span><span style="color:#282828;">docker-compose up -d</span><span style="color:#b23c15;">;
</span></code></pre>
Github Actions Build Hugo Static Site and Archive Build Result to Artifact
2022-02-16T19:10:13+07:00
2022-02-16T19:10:13+07:00
Unknown
https://www.sumarsono.com/github-actions-build-hugo-static-site-and-archive-build-result-to-artifact/
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">cat .github/workflows/main.yml
</span></code></pre>
<pre data-lang="yaml" style="background-color:#fcf0ca;color:#282828aa;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">Build Hugo Static Website
</span><span>
</span><span style="color:#8f3f71;">on</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">push</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">branches</span><span>: [ </span><span style="color:#79740e;">hugo.sumarsono.com </span><span>]
</span><span> </span><span style="font-weight:bold;color:#407959;">pull_request</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">branches</span><span>: [ </span><span style="color:#79740e;">main </span><span>]
</span><span>
</span><span> </span><span style="font-style:italic;color:#928374;"># Allows you to run this workflow manually from the Actions tab
</span><span> </span><span style="font-weight:bold;color:#407959;">workflow_dispatch</span><span>:
</span><span>
</span><span style="font-weight:bold;color:#407959;">jobs</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">deploy</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">runs-on</span><span>: </span><span style="color:#79740e;">ubuntu-20.04
</span><span> </span><span style="font-weight:bold;color:#407959;">concurrency</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">group</span><span>: </span><span style="color:#79740e;">${{ github.workflow }}-${{ github.ref }}
</span><span> </span><span style="font-weight:bold;color:#407959;">steps</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">Git checkout and update theme
</span><span> </span><span style="font-weight:bold;color:#407959;">uses</span><span>: </span><span style="color:#79740e;">actions/checkout@v2
</span><span> </span><span style="font-weight:bold;color:#407959;">with</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">submodules</span><span>: </span><span style="color:#8f3f71;">true </span><span style="font-style:italic;color:#928374;"># Fetch Hugo themes (true OR recursive)
</span><span> </span><span style="font-weight:bold;color:#407959;">fetch-depth</span><span>: </span><span style="color:#8f3f71;">0 </span><span style="font-style:italic;color:#928374;"># Fetch all history for .GitInfo and .Lastmod
</span><span>
</span><span> - </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">Get commit short SHA
</span><span> </span><span style="font-weight:bold;color:#407959;">run</span><span>: </span><span style="color:#79740e;">echo "SHORT_SHA=`git rev-parse --short HEAD`" >> $GITHUB_ENV
</span><span>
</span><span> - </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">Setup hugo
</span><span> </span><span style="font-weight:bold;color:#407959;">uses</span><span>: </span><span style="color:#79740e;">peaceiris/actions-hugo@v2
</span><span> </span><span style="font-weight:bold;color:#407959;">with</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">hugo-version</span><span>: </span><span style="color:#79740e;">"0.92.2"
</span><span> </span><span style="font-weight:bold;color:#407959;">extended</span><span>: </span><span style="color:#8f3f71;">true
</span><span>
</span><span> - </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">Cache Hugo module
</span><span> </span><span style="font-weight:bold;color:#407959;">uses</span><span>: </span><span style="color:#79740e;">actions/cache@v2
</span><span> </span><span style="font-weight:bold;color:#407959;">with</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">path</span><span>: </span><span style="color:#79740e;">/tmp/hugo_cache
</span><span> </span><span style="font-weight:bold;color:#407959;">key</span><span>: </span><span style="color:#79740e;">${{ runner.os }}-hugomod-${{ hashFiles('**/go.sum') }}
</span><span> </span><span style="font-weight:bold;color:#407959;">restore-keys</span><span>: </span><span style="color:#9d0006;">|
</span><span style="color:#79740e;"> ${{ runner.os }}-hugomod-
</span><span style="color:#79740e;">
</span><span> - </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">Build website
</span><span> </span><span style="font-weight:bold;color:#407959;">run</span><span>: </span><span style="color:#79740e;">hugo --minify
</span><span>
</span><span> - </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">Archive build result to artifacts
</span><span> </span><span style="font-weight:bold;color:#407959;">uses</span><span>: </span><span style="color:#79740e;">actions/upload-artifact@v2
</span><span> </span><span style="font-weight:bold;color:#407959;">with</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">build-result-${{ env.SHORT_SHA }}
</span><span> </span><span style="font-weight:bold;color:#407959;">path</span><span>: </span><span style="color:#9d0006;">|
</span><span style="color:#79740e;"> public
</span></code></pre>
Ubuntu 20.04 Tagged Vlan
2022-02-14T10:50:26+07:00
2022-02-14T10:50:26+07:00
Unknown
https://www.sumarsono.com/ubuntu-20-04-tagged-vlan/
<p>Sedikit konteks, aku ingin memisahkan server di rumah dari jangkauan WiFi, krn WiFi dipakai banyak orang. Sehingga aku pisahkan koneksi server di rumah dengan WiFi memakai tagged VLAN. Ubuntu 20.04 server by default menggunakan netplan untuk konfigurasi network-nya. Berikut ini adalah konfigurasi netplan untuk tagged vlan:</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">sudo cat /etc/netplan/00-eth0.yaml
</span></code></pre>
<pre data-lang="yaml" style="background-color:#fcf0ca;color:#282828aa;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span style="font-weight:bold;color:#407959;">network</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">version</span><span>: </span><span style="color:#8f3f71;">2
</span><span> </span><span style="font-weight:bold;color:#407959;">ethernets</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">eth0</span><span>: {}
</span><span> </span><span style="font-weight:bold;color:#407959;">vlans</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">vlan10</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">id</span><span>: </span><span style="color:#8f3f71;">10
</span><span> </span><span style="font-weight:bold;color:#407959;">link</span><span>: </span><span style="color:#79740e;">eth0
</span><span> </span><span style="font-weight:bold;color:#407959;">addresses</span><span>: [</span><span style="color:#79740e;">192.168.10.2/24</span><span>]
</span><span> </span><span style="font-weight:bold;color:#407959;">routes</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">to</span><span>: </span><span style="color:#79740e;">default
</span><span> </span><span style="font-weight:bold;color:#407959;">via</span><span>: </span><span style="color:#8f3f71;">192.168.10.1
</span></code></pre>
<p>Konfigurasi diatas akan membuat kita terhubung dengan vlan tag 10.</p>
Openwrt Adguardhome Dns Hijack
2022-01-21T20:30:54+07:00
2022-01-21T20:30:54+07:00
Unknown
https://www.sumarsono.com/openwrt-adguardhome-dns-hijack/
<p>Aku punya router Openwrt 21.02.1, adapun yang terhubung ke <code>lan</code> openwrt: Raspbery Pi 3B, Laptop, dan HP.
Aku menjadikan Raspbery Pi sebagai server kecil, memanfaatkan cloudflare argo tunnel dan docker. Salah satu aplikasi yang aku pasang di raspbery pi adalah AdGuardHome. Aku memasang AdGuardHome menggunakan docker compose:</p>
<pre data-lang="yaml" style="background-color:#fcf0ca;color:#282828aa;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span style="font-weight:bold;color:#407959;">version</span><span>: </span><span style="color:#79740e;">'3.3'
</span><span style="font-weight:bold;color:#407959;">services</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">adguardhome</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">container_name</span><span>: </span><span style="color:#79740e;">adguardhome
</span><span> </span><span style="font-weight:bold;color:#407959;">restart</span><span>: </span><span style="color:#79740e;">unless-stopped
</span><span> </span><span style="font-weight:bold;color:#407959;">volumes</span><span>:
</span><span> - </span><span style="color:#79740e;">'./workdir:/opt/adguardhome/work'
</span><span> - </span><span style="color:#79740e;">'./confdir:/opt/adguardhome/conf'
</span><span> </span><span style="font-weight:bold;color:#407959;">network_mode</span><span>: </span><span style="color:#79740e;">host
</span><span> </span><span style="font-weight:bold;color:#407959;">image</span><span>: </span><span style="color:#79740e;">adguard/adguardhome
</span></code></pre>
<p>Sekarang, aku ingin semua query dns yang masuk ke router Openwrt dihandle oleh AdGuardHome yang ada di Raspbery Pi. Aku sudah set dhcp option untuk assign ip address raspbery pi sebagai dns ke klien, wan dns juga sudah diarahkan ke raspbery pi, dnsmasq juga sudah forward ke raspbery pi. Tapi hasilnya kurang memuaskan, banyak query yang gak lewat AdGuardHome.</p>
<p>Setelah membaca wiki openwrt, aku menemukan cara untuk hijack dns melalui firewall openwrt. Begini caranya:</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="font-style:italic;color:#928374;"># Intercept DNS traffic
</span><span style="color:#282828;">uci -q delete firewall.dns_int
</span><span style="color:#282828;">uci set firewall.dns_int=</span><span style="color:#79740e;">"redirect"
</span><span style="color:#282828;">uci set firewall.dns_int.name=</span><span style="color:#79740e;">"Intercept-DNS"
</span><span style="color:#282828;">uci set firewall.dns_int.src=</span><span style="color:#79740e;">"lan"
</span><span style="color:#282828;">uci set firewall.dns_int.src_dport=</span><span style="color:#79740e;">"53"
</span><span style="color:#282828;">uci set firewall.dns_int.proto=</span><span style="color:#79740e;">"tcp udp"
</span><span style="color:#282828;">uci set firewall.dns_int.target=</span><span style="color:#79740e;">"DNAT"
</span><span style="color:#282828;">uci commit firewall
</span><span style="color:#282828;">/etc/init.d/firewall restart
</span><span>
</span><span style="font-style:italic;color:#928374;"># Configure firewall to exclude the local DNS server from the interception rule
</span><span style="color:#282828;">uci set firewall.dns_int.src_mac=</span><span style="color:#79740e;">"!00:11:22:33:44:55"
</span><span style="color:#282828;">uci commit firewall
</span><span style="color:#282828;">/etc/init.d/firewall restart
</span></code></pre>
<p>Ganti <code>00:11:22:33:44:55</code> dengan MAC address Raspbery Pi yang digunakan</p>
<p>Dan Boom, cek di https://dnsleaktest.com/ dns sudah sesuai dengan yang di set di AdGuardHome.</p>
<p>Referensi:</p>
<ul>
<li>https://openwrt.org/docs/guide-user/firewall/fw3_configurations/intercept_dns</li>
</ul>
Ghost docker-compose.yaml
2022-01-21T16:25:08+07:00
2022-01-21T16:25:08+07:00
Unknown
https://www.sumarsono.com/ghost-docker-compose-yaml/
<p>Ghost docker compose include SES for SMTP and Nginx Proxy Manager</p>
<pre data-lang="yaml" style="background-color:#fcf0ca;color:#282828aa;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span style="font-weight:bold;color:#407959;">version</span><span>: </span><span style="color:#79740e;">'3.3'
</span><span style="font-weight:bold;color:#407959;">services</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">ghost</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">image</span><span>: </span><span style="color:#79740e;">'ghost:4.32.3'
</span><span> </span><span style="font-weight:bold;color:#407959;">container_name</span><span>: </span><span style="color:#79740e;">ghost-service
</span><span> </span><span style="font-weight:bold;color:#407959;">volumes</span><span>:
</span><span> - </span><span style="color:#79740e;">'/home/sumar/ghost/data:/var/lib/ghost/content'
</span><span> </span><span style="font-weight:bold;color:#407959;">restart</span><span>: </span><span style="color:#79740e;">unless-stopped
</span><span> </span><span style="font-weight:bold;color:#407959;">environment</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">url</span><span>: </span><span style="color:#79740e;">http://ghost.sumarsono.com
</span><span> </span><span style="font-weight:bold;color:#407959;">mail__from</span><span>: </span><span style="color:#79740e;">noreply-ghost@sumarsono.com
</span><span> </span><span style="font-weight:bold;color:#407959;">mail__transport</span><span>: </span><span style="color:#79740e;">SMTP
</span><span> </span><span style="font-weight:bold;color:#407959;">mail__options__host</span><span>: </span><span style="color:#79740e;">SES-SMTP-host
</span><span> </span><span style="font-weight:bold;color:#407959;">mail__options__port</span><span>: </span><span style="color:#79740e;">SES-SMTP-port
</span><span> </span><span style="font-weight:bold;color:#407959;">mail__options__service</span><span>: </span><span style="color:#79740e;">SES
</span><span> </span><span style="font-weight:bold;color:#407959;">mail__options__auth__user</span><span>: </span><span style="color:#79740e;">SES-SMTP-username
</span><span> </span><span style="font-weight:bold;color:#407959;">mail__options__auth__pass</span><span>: </span><span style="color:#79740e;">SES-SMTP-password
</span><span>
</span><span style="font-weight:bold;color:#407959;">networks</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">default</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">external</span><span>: </span><span style="color:#8f3f71;">true
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">nginx-proxy-manager
</span></code></pre>
Contact
2022-01-09T08:00:00+07:00
2022-01-09T08:00:00+07:00
Unknown
https://www.sumarsono.com/contact/
<p>Feel free to contact me at</p>
<ul>
<li><a href="mailto:gmail@sumarsono.com">Email</a></li>
<li><a href="https://t.me/nalakawula">Telegram</a></li>
</ul>
About
2022-01-01T08:00:00+07:00
2022-01-01T08:00:00+07:00
Unknown
https://www.sumarsono.com/about/
<p>Aku Sumarsono, panggil saja Sumar.</p>
<h2 id="pengalaman-kerja">Pengalaman Kerja</h2>
<p>[Redacted, privacy reason]</p>
<h2 id="tentang-situs-ini">Tentang situs ini</h2>
<p>sumarsono.com dibangun menggunakan static site generator yang bernama zola dengan tema <a href="https://github.com/carpetscheme/lightspeed">lightspeed</a>.</p>
<p>Semua artikel disini berlisensi <img src="https://licensebuttons.net/l/by-nc-sa/4.0/80x15.png" alt="https://creativecommons.org/licenses/by-nc-sa/4.0/" /> kecuali untuk gambar/logo/cuplikan/apapun yang dinukil dari tempat lain, lisensinya ikut lisensi pemilik asli.</p>
<h2 id="disclaimer">Disclaimer</h2>
<p>Pertama, Always take with a grain of salt. Jangan makan mentah-mentah atas apa yang tertulis pada artikel di situs sumarsono.com.
Artikel di sini kebanyakan adalah pengalaman pribadi dan banyak bersumber dari internet, jadi jangan anggap mutlak benar.</p>
<p>Kedua, aku tidak mengklaim semua asset yang diambil dari luar sebagai hak milik. Asset-asset yang bersumber dari luar adalah hak milik pemilik asli, dan lisensinya mengikuti lisensi dari pemilik asli. Jika ada asset dari luar yang melanggar hak milik/lisensi, silakan jkontak lewat email atau telegram, asset yang bersangkutan akan lansgung aku hapus dari situs ini.</p>
Encrypt File
2022-01-01T08:00:00+07:00
2022-01-01T08:00:00+07:00
Unknown
https://www.sumarsono.com/encrypt/
<h2 id="mengirim-file-terenkripsi-kepadaku">Mengirim file terenkripsi kepadaku</h2>
<p>Jika kamu ingin mengirim file terenkripsi kepadaku, silakan gunakan <a href="https://github.com/FiloSottile/age">age</a> atau <a href="https://github.com/str4d/rage">rage</a> dengan <a href="https://www.sumarsono.com/agekeys">public key www.sumarsono.com/agekeys</a>.</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">curl https://www.sumarsono.com/agekeys </span><span style="color:#b23c15;">| </span><span style="color:#282828;">age -R - /path/to/file/rahasia.docx </span><span style="color:#b23c15;">></span><span style="color:#282828;"> /path/to/file/rahasia.docx.age
</span></code></pre>
<p>Kemudian kirim file <code>/path/to/file/rahasia.docx.age</code> kepadaku, hanya aku yang punya private key untuk membuka file tersebut.</p>
<p>Thanks</p>
<p>Ref: </p>
<ul>
<li><a href="https://github.com/FiloSottile/age">https://github.com/FiloSottile/age</a></li>
<li><a href="https://manpages.ubuntu.com/manpages/kinetic/en/man1/age.1.html">https://manpages.ubuntu.com/manpages/kinetic/en/man1/age.1.html</a></li>
</ul>
Coredns Pm2 Ecosystem
2021-11-30T18:59:44+07:00
2021-11-30T18:59:44+07:00
Unknown
https://www.sumarsono.com/coredns-pm2-ecosystem/
<p>Salah satu cara untuk membuat daemon coredns yang universal (bisa di linux dan mac os) adalah menggunakan pm2. Pertama kita generate <code>ecosystem.config.js</code></p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">pm2 init simple
</span></code></pre>
<p>edit <code>ecosystem.config.js</code> menjadi:</p>
<pre data-lang="js" style="background-color:#fcf0ca;color:#282828aa;" class="language-js "><code class="language-js" data-lang="js"><span style="color:#b57614;">module</span><span>.</span><span style="color:#b57614;">exports </span><span style="color:#b23c15;">= </span><span>{
</span><span> apps : [{
</span><span> name : </span><span style="color:#79740e;">"CoreDNS"</span><span>,
</span><span> script : </span><span style="color:#79740e;">"/Users/sumar/opt/coredns"</span><span>,
</span><span> args: </span><span style="color:#79740e;">"-conf /Users/sumar/etc/coredns/Corefile"</span><span>,
</span><span> max_memory_restart: </span><span style="color:#79740e;">"100M"</span><span>,
</span><span> instances: </span><span style="color:#79740e;">"1"
</span><span> }]
</span><span>}
</span></code></pre>
<p>isi dari <code>/Users/sumar/etc/coredns/Corefile</code></p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>.:53 {
</span><span> any
</span><span> errors
</span><span> log
</span><span>
</span><span> forward . tls://8.8.8.8 tls://8.8.4.4 {
</span><span> tls_servername dns.google
</span><span> health_check 60s
</span><span> }
</span><span>}
</span><span>
</span><span>internal-site.localdomain:53 {
</span><span> file /Users/sumar/etc/coredns/internal-site.localdomain.db
</span><span> log
</span><span> errors
</span><span>}
</span></code></pre>
<p>untuk start:</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">pm2 start ecosystem.config.js
</span></code></pre>
<p>Outputnya:</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">[PM2] Applying action restartProcessId on app </span><span style="color:#9d0006;">[</span><span style="color:#282828;">CoreDNS</span><span style="color:#9d0006;">]</span><span style="color:#282828;">(ids: </span><span style="color:#9d0006;">[</span><span style="color:#282828;"> 0 </span><span style="color:#9d0006;">]</span><span>)
</span><span style="color:#282828;">[PM2] </span><span style="color:#9d0006;">[</span><span style="color:#282828;">CoreDNS</span><span style="color:#9d0006;">]</span><span style="color:#282828;">(0</span><span>) </span><span style="color:#282828;">✓
</span><span style="color:#282828;">┌─────┬────────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐
</span><span style="color:#282828;">│ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ user │ watching │
</span><span style="color:#282828;">├─────┼────────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤
</span><span style="color:#282828;">│ 0 │ CoreDNS │ default │ N/A │ fork │ 4604 │ 0s │ 1 │ online │ 0% │ 5.4mb │ sumar │ disabled │
</span><span style="color:#282828;">└─────┴────────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘
</span></code></pre>
Freebsd Install Mysql Server
2021-11-27T18:42:57+07:00
2021-11-27T18:42:57+07:00
Unknown
https://www.sumarsono.com/freebsd-install-mysql-server/
<h2 id="install-mysql-server">Install mysql server:</h2>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">root@freebsd:~ </span><span style="font-style:italic;color:#928374;"># pkg install mysql57-server
</span><span style="color:#282828;">Updating FreeBSD repository catalogue...
</span><span style="color:#282828;">FreeBSD repository is up to date.
</span><span style="color:#282828;">All repositories are up to date.
</span><span style="color:#282828;">The following 18 package(s</span><span>) </span><span style="color:#282828;">will be affected (of 0 checked</span><span>)</span><span style="color:#b57614;">:
</span><span>
</span><span style="color:#282828;">New packages to be INSTALLED:
</span><span> </span><span style="color:#282828;">ca_root_nss: 3.69_1
</span><span> </span><span style="color:#282828;">curl: 7.79.1
</span><span> </span><span style="color:#282828;">cyrus-sasl: 2.1.27_2
</span><span> </span><span style="color:#282828;">groff: 1.22.4_4
</span><span> </span><span style="color:#282828;">libedit: 3.1.20210216,1
</span><span> </span><span style="color:#282828;">libevent: 2.1.12
</span><span> </span><span style="color:#282828;">libiconv: 1.16
</span><span> </span><span style="color:#282828;">liblz4: 1.9.3,1
</span><span> </span><span style="color:#282828;">libnghttp2: 1.44.0
</span><span> </span><span style="color:#282828;">libpaper: 1.1.24.4
</span><span> </span><span style="color:#282828;">libssh2: 1.9.0_3,3
</span><span> </span><span style="color:#282828;">mysql57-client: 5.7.36
</span><span> </span><span style="color:#282828;">mysql57-server: 5.7.36
</span><span> </span><span style="color:#282828;">openldap24-client: 2.4.59_2
</span><span> </span><span style="color:#282828;">perl5: 5.32.1_1
</span><span> </span><span style="color:#282828;">protobuf: 3.17.3,1
</span><span> </span><span style="color:#282828;">psutils: 1.17_5
</span><span> </span><span style="color:#282828;">uchardet: 0.0.7
</span><span>
</span><span style="color:#282828;">Number of packages to be installed: 18
</span><span>
</span><span style="color:#282828;">The process will require 319 MiB more space.
</span><span style="color:#282828;">41 MiB to be downloaded.
</span><span>
</span><span style="color:#282828;">Proceed with this action</span><span style="color:#b23c15;">? </span><span style="color:#9d0006;">[</span><span style="color:#282828;">y/N</span><span style="color:#9d0006;">]</span><span style="color:#282828;">: y
</span></code></pre>
<h2 id="enable-mysql-server-service">Enable mysql server service:</h2>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">root@freebsd:~ </span><span style="font-style:italic;color:#928374;"># sysrc mysql_enable="yes"
</span><span style="color:#282828;">mysql_enable: -</span><span style="color:#b23c15;">></span><span style="color:#282828;"> yes
</span><span style="color:#282828;">root@freebsd:~ </span><span style="font-style:italic;color:#928374;"># service mysql status
</span><span style="color:#282828;">mysql does not exist in /etc/rc.d or the local startup
</span><span style="color:#282828;">directories (/usr/local/etc/rc.d</span><span>)</span><span style="color:#282828;">, or is not executable
</span><span style="color:#282828;">root@freebsd:~ </span><span style="font-style:italic;color:#928374;"># service mysql-server status
</span><span style="color:#282828;">mysql is not running.
</span><span style="color:#282828;">root@freebsd:~ </span><span style="font-style:italic;color:#928374;"># service mysql-server start
</span><span style="color:#282828;">Starting mysql.
</span><span style="color:#282828;">root@freebsd:~ </span><span style="font-style:italic;color:#928374;"># service mysql-server status
</span></code></pre>
<h2 id="get-mysql-initial-root-password">Get mysql initial root password:</h2>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">mysql is running as pid 4280.
</span><span style="color:#282828;">root@freebsd:~ </span><span style="font-style:italic;color:#928374;"># cat /root/.mysql_secret
</span><span style="font-style:italic;color:#928374;"># Password set for user 'root@localhost' at 2021-11-21 23:49:10
</span><span style="color:#282828;">5oWB</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">ea:pJSh
</span></code></pre>
<h2 id="secure-mysql-server-installation">Secure mysql server installation:</h2>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">root@freebsd:~ </span><span style="font-style:italic;color:#928374;"># mysql_secure_installation
</span><span style="color:#282828;">Securing the MySQL server deployment.
</span><span>
</span><span style="color:#282828;">Connecting to MySQL server using password in </span><span style="color:#79740e;">'/root/.mysql_secret'
</span><span>
</span><span style="color:#282828;">VALIDATE PASSWORD PLUGIN can be used to test passwords
</span><span style="color:#282828;">and improve security. It checks the strength of password
</span><span style="color:#282828;">and allows the users to set only those passwords which are
</span><span style="color:#282828;">secure enough. Would you like to setup VALIDATE PASSWORD plugin</span><span style="color:#b23c15;">?
</span><span>
</span><span style="color:#282828;">Press y</span><span style="color:#b23c15;">|</span><span style="color:#282828;">Y for Yes, any other key for No: y
</span><span>
</span><span style="color:#282828;">There are three levels of password validation policy:
</span><span>
</span><span style="color:#282828;">LOW Length </span><span style="color:#b23c15;">></span><span style="color:#282828;">= 8
</span><span style="color:#282828;">MEDIUM Length </span><span style="color:#b23c15;">></span><span style="color:#282828;">= 8, numeric, mixed case, and special characters
</span><span style="color:#282828;">STRONG Length </span><span style="color:#b23c15;">></span><span style="color:#282828;">= 8, numeric, mixed case, special characters and dictionary file
</span><span>
</span><span style="color:#282828;">Please enter 0 = LOW, 1 = MEDIUM and 2 = STRONG: 0
</span><span style="color:#282828;">Using existing password for root.
</span><span>
</span><span style="color:#282828;">Estimated strength of the password: 100
</span><span>
</span><span style="color:#282828;">Change the password for root </span><span style="color:#b23c15;">?</span><span style="color:#282828;"> ((Press y</span><span style="color:#b23c15;">|</span><span style="color:#282828;">Y for Yes, any other key for No</span><span>) </span><span style="color:#b57614;">:</span><span style="color:#282828;"> Y
</span><span>
</span><span style="color:#282828;">New password:
</span><span>
</span><span style="color:#282828;">Re-enter new password:
</span><span>
</span><span style="color:#282828;">Estimated strength of the password: 50
</span><span style="color:#282828;">Do you wish to continue with the password provided</span><span style="color:#b23c15;">?</span><span style="color:#282828;">(Press y</span><span style="color:#b23c15;">|</span><span style="color:#282828;">Y for Yes, any other key for No) : y
</span><span style="color:#282828;">By default, a MySQL installation has an anonymous user,
</span><span style="color:#282828;">allowing anyone to log into MySQL without having to have
</span><span style="color:#282828;">a user account created for them. This is intended only for
</span><span style="color:#282828;">testing, and to make the installation go a bit smoother.
</span><span style="color:#282828;">You should remove them before moving into a production
</span><span style="color:#282828;">environment.
</span><span>
</span><span style="color:#282828;">Remove anonymous users</span><span style="color:#b23c15;">?</span><span style="color:#282828;"> (Press y</span><span style="color:#b23c15;">|</span><span style="color:#282828;">Y for Yes, any other key for No</span><span>) </span><span style="color:#b57614;">:</span><span style="color:#282828;"> y
</span><span style="color:#282828;">Success.
</span><span>
</span><span>
</span><span style="color:#282828;">Normally, root should only be allowed to connect from
</span><span style="color:#79740e;">'localhost'</span><span style="color:#282828;">. This ensures that someone cannot guess at
</span><span style="color:#282828;">the root password from the network.
</span><span>
</span><span style="color:#282828;">Disallow root login remotely</span><span style="color:#b23c15;">?</span><span style="color:#282828;"> (Press y</span><span style="color:#b23c15;">|</span><span style="color:#282828;">Y for Yes, any other key for No</span><span>) </span><span style="color:#b57614;">:</span><span style="color:#282828;"> y
</span><span style="color:#282828;">Success.
</span><span>
</span><span style="color:#282828;">By default, MySQL comes with a database named </span><span style="color:#79740e;">'test'</span><span style="color:#282828;"> that
</span><span style="color:#282828;">anyone can access. This is also intended only for testing,
</span><span style="color:#282828;">and should be removed before moving into a production
</span><span style="color:#282828;">environment.
</span><span>
</span><span>
</span><span style="color:#282828;">Remove test database and access to it</span><span style="color:#b23c15;">?</span><span style="color:#282828;"> (Press y</span><span style="color:#b23c15;">|</span><span style="color:#282828;">Y for Yes, any other key for No</span><span>) </span><span style="color:#b57614;">:</span><span style="color:#282828;"> y
</span><span> </span><span style="color:#282828;">- Dropping test database...
</span><span style="color:#282828;">Success.
</span><span>
</span><span> </span><span style="color:#282828;">- Removing privileges on test database...
</span><span style="color:#282828;">Success.
</span><span>
</span><span style="color:#282828;">Reloading the privilege tables will ensure that all changes
</span><span style="color:#282828;">made so far will take effect immediately.
</span><span>
</span><span style="color:#282828;">Reload privilege tables now</span><span style="color:#b23c15;">?</span><span style="color:#282828;"> (Press y</span><span style="color:#b23c15;">|</span><span style="color:#282828;">Y for Yes, any other key for No</span><span>) </span><span style="color:#b57614;">:</span><span style="color:#282828;"> y
</span><span style="color:#282828;">Success.
</span><span>
</span><span style="color:#282828;">All done!
</span><span>
</span><span style="color:#282828;">root@freebsd:~ </span><span style="font-style:italic;color:#928374;">#
</span></code></pre>
Freebsd Install Nginx
2021-11-27T16:57:41+07:00
2021-11-27T16:57:41+07:00
Unknown
https://www.sumarsono.com/freebsd-install-nginx/
<h2 id="install-nginx">Install nginx:</h2>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">root@freebsd:~ </span><span style="font-style:italic;color:#928374;"># pkg install nginx
</span><span style="color:#282828;">Updating FreeBSD repository catalogue...
</span><span style="color:#282828;">FreeBSD repository is up to date.
</span><span style="color:#282828;">All repositories are up to date.
</span><span style="color:#282828;">The following 2 package(s</span><span>) </span><span style="color:#282828;">will be affected (of 0 checked</span><span>)</span><span style="color:#b57614;">:
</span><span>
</span><span style="color:#282828;">New packages to be INSTALLED:
</span><span> </span><span style="color:#282828;">nginx: 1.20.1_3,2
</span><span> </span><span style="color:#282828;">pcre: 8.45
</span><span>
</span><span style="color:#282828;">Number of packages to be installed: 2
</span><span>
</span><span style="color:#282828;">The process will require 8 MiB more space.
</span><span style="color:#282828;">2 MiB to be downloaded.
</span><span>
</span><span style="color:#282828;">Proceed with this action</span><span style="color:#b23c15;">? </span><span style="color:#9d0006;">[</span><span style="color:#282828;">y/N</span><span style="color:#9d0006;">]</span><span style="color:#282828;">: y
</span><span style="color:#282828;">[1/2] Fetching nginx-1.20.1_3,2.pkg: 100% 458 KiB 117.3kB/s 00:04
</span><span style="color:#282828;">[2/2] Fetching pcre-8.45.pkg: 100% 1 MiB 104.3kB/s 00:12
</span><span style="color:#282828;">Checking integrity... done (0 conflicting</span><span>)
</span><span style="color:#282828;">[1/2] Installing pcre-8.45...
</span><span style="color:#282828;">[1/2] Extracting pcre-8.45: 100%
</span><span style="color:#282828;">[2/2] Installing nginx-1.20.1_3,2...
</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">==</span><span style="color:#b23c15;">></span><span> Creating </span><span style="color:#282828;">groups.
</span><span style="color:#282828;">Using existing group </span><span style="color:#79740e;">'www'</span><span style="color:#282828;">.
</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">==</span><span style="color:#b23c15;">></span><span> Creating </span><span style="color:#282828;">users
</span><span style="color:#282828;">Using existing user </span><span style="color:#79740e;">'www'</span><span style="color:#282828;">.
</span><span style="color:#282828;">[2/2] Extracting nginx-1.20.1_3,2: 100%
</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">====
</span><span style="color:#282828;">Message from nginx-1.20.1_3,2:
</span><span>
</span><span style="color:#282828;">--
</span><span style="color:#282828;">Recent version of the NGINX introduces dynamic modules support. In
</span><span style="color:#282828;">FreeBSD ports tree this feature was enabled by default with the DSO
</span><span style="color:#282828;">knob. Several vendor</span><span style="color:#79740e;">'s and third-party modules have been converted
</span><span style="color:#79740e;">to dynamic modules. Unset the DSO knob builds an NGINX without
</span><span style="color:#79740e;">dynamic modules support.
</span><span style="color:#79740e;">
</span><span style="color:#79740e;">To load a module at runtime, include the new `load_module'
</span><span style="color:#282828;">directive in the main context, specifying the path to the shared
</span><span style="color:#282828;">object file for the module, enclosed in quotation marks. When you
</span><span style="color:#282828;">reload the configuration or restart NGINX, the module is loaded in.
</span><span style="color:#282828;">It is possible to specify a path relative to the source directory,
</span><span style="color:#282828;">or a full path, please see
</span><span style="color:#282828;">https://www.nginx.com/blog/dynamic-modules-nginx-1-9-11/ and
</span><span style="color:#282828;">http://nginx.org/en/docs/ngx_core_module.html#load_module for
</span><span style="color:#282828;">details.
</span><span>
</span><span style="color:#282828;">Default path for the NGINX dynamic modules is
</span><span>
</span><span style="color:#282828;">/usr/local/libexec/nginx.
</span></code></pre>
<h2 id="enable-service-nginx">Enable service nginx:</h2>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">root@freebsd:~ </span><span style="font-style:italic;color:#928374;"># sysrc nginx_enable="yes"
</span><span style="color:#282828;">nginx_enable: -</span><span style="color:#b23c15;">></span><span style="color:#282828;"> yes
</span></code></pre>
<p>command tadi akan menambahkan baris <code>nginx_enable="yes"</code> pada file <code>/etc/rc.conf</code></p>
<h2 id="start-service-nginx">Start service nginx:</h2>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">root@freebsd:~ </span><span style="font-style:italic;color:#928374;"># service nginx status
</span><span style="color:#282828;">nginx is not running.
</span><span style="color:#282828;">root@freebsd:~ </span><span style="font-style:italic;color:#928374;"># service nginx start
</span><span style="color:#282828;">Performing sanity check on nginx configuration:
</span><span style="color:#282828;">nginx: the configuration file /usr/local/etc/nginx/nginx.conf syntax is ok
</span><span style="color:#282828;">nginx: configuration file /usr/local/etc/nginx/nginx.conf test is successful
</span><span style="color:#282828;">Starting nginx.
</span><span style="color:#282828;">root@freebsd:~ </span><span style="font-style:italic;color:#928374;"># service nginx status
</span><span style="color:#282828;">nginx is running as pid 2545.
</span></code></pre>
<h2 id="konfigurasi-nginx-freebsd-ada-di">Konfigurasi nginx freebsd ada di:</h2>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>/usr/local/etc/nginx/
</span></code></pre>
<h2 id="mencoba-edit-konfigurasi-nginx">Mencoba edit konfigurasi nginx</h2>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">ee /usr/local/etc/nginx/nginx.conf
</span><span>
</span><span style="color:#282828;">...
</span><span style="color:#282828;">...
</span><span> </span><span style="color:#282828;">location / {
</span><span style="color:#282828;"> default_type application/json;
</span><span style="color:#282828;"> return 200 </span><span style="color:#79740e;">'{"code":"0", "message": "I am alive"}'</span><span style="color:#282828;">;
</span><span style="color:#282828;">
</span><span style="color:#282828;"> root /usr/local/www/nginx;
</span><span style="color:#282828;"> index index.html index.htm;
</span><span style="color:#282828;"> }
</span><span style="color:#282828;">...
</span><span style="color:#282828;">...
</span></code></pre>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">sumar@Sumarsonos-MacBook-Air ~ % curl -i http://10.211.55.5
</span><span style="color:#282828;">HTTP/1.1 200 OK
</span><span style="color:#282828;">Server: nginx/1.20.1
</span><span style="color:#282828;">Date: Sun, 21 Nov 2021 17:16:20 GMT
</span><span style="color:#282828;">Content-Type: application/json
</span><span style="color:#282828;">Content-Length: 37
</span><span style="color:#282828;">Connection: keep-alive
</span><span>
</span><span style="color:#282828;">{</span><span style="color:#79740e;">"code"</span><span style="color:#282828;">:</span><span style="color:#79740e;">"0"</span><span style="color:#282828;">, </span><span style="color:#79740e;">"message"</span><span style="color:#282828;">: </span><span style="color:#79740e;">"I am alive"</span><span>}</span><span style="color:#282828;">%
</span></code></pre>
Freebsd Check Listening Port
2021-11-27T16:53:48+07:00
2021-11-27T16:53:48+07:00
Unknown
https://www.sumarsono.com/freebsd-check-listening-port/
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">root@freebsd:~ </span><span style="font-style:italic;color:#928374;"># sockstat -l
</span><span style="color:#282828;">USER COMMAND PID FD PROTO LOCAL ADDRESS FOREIGN ADDRESS
</span><span style="color:#282828;">www nginx 2546 6 tcp4 </span><span style="color:#b23c15;">*</span><span style="color:#282828;">:80 </span><span style="color:#b23c15;">*</span><span style="color:#282828;">:</span><span style="color:#b23c15;">*
</span><span style="color:#282828;">root nginx 2545 6 tcp4 </span><span style="color:#b23c15;">*</span><span style="color:#282828;">:80 </span><span style="color:#b23c15;">*</span><span style="color:#282828;">:</span><span style="color:#b23c15;">*
</span><span style="color:#282828;">root sshd 2158 6 stream (not connected</span><span>)
</span><span style="color:#282828;">root sshd 1230 3 tcp6 </span><span style="color:#b23c15;">*</span><span style="color:#282828;">:22 </span><span style="color:#b23c15;">*</span><span style="color:#282828;">:</span><span style="color:#b23c15;">*
</span><span style="color:#282828;">root sshd 1230 4 tcp4 </span><span style="color:#b23c15;">*</span><span style="color:#282828;">:22 </span><span style="color:#b23c15;">*</span><span style="color:#282828;">:</span><span style="color:#b23c15;">*
</span><span style="color:#282828;">root sendmail 970 4 tcp4 127.0.0.1:25 </span><span style="color:#b23c15;">*</span><span style="color:#282828;">:</span><span style="color:#b23c15;">*
</span><span style="color:#282828;">root syslogd 877 6 udp6 </span><span style="color:#b23c15;">*</span><span style="color:#282828;">:514 </span><span style="color:#b23c15;">*</span><span style="color:#282828;">:</span><span style="color:#b23c15;">*
</span><span style="color:#282828;">root syslogd 877 7 udp4 </span><span style="color:#b23c15;">*</span><span style="color:#282828;">:514 </span><span style="color:#b23c15;">*</span><span style="color:#282828;">:</span><span style="color:#b23c15;">*
</span><span style="color:#282828;">root syslogd 877 8 dgram /var/run/log
</span><span style="color:#282828;">root syslogd 877 9 dgram /var/run/logpriv
</span><span style="color:#282828;">root devd 680 4 stream /var/run/devd.pipe
</span><span style="color:#282828;">root devd 680 5 seqpac /var/run/devd.seqpacket.pipe
</span></code></pre>
Nginx Basic Auth Dengan Pengecualian
2021-11-20T17:18:11+07:00
2021-11-20T17:18:11+07:00
Unknown
https://www.sumarsono.com/nginx-basic-auth-dengan-pengecualian/
<p>Aku ada aplikasi yang dibuat pakai Laravel. Dari aplikasi itu mau dipasangin basic auth dengan pengecualian. Maksudnya ada beberapa part yang tidak ingin dipakaikan basic auth.</p>
<p>Misalnya gini: </p>
<ul>
<li>Basic auth off jika diakses pakai ip tertentu..</li>
<li>Basic auth off jika request uri <code>/?webhook-author=sumar&notification-target=telegram</code></li>
<li>Jika tidak memenuhi kondisi diatas, maka basic auth on.</li>
</ul>
<p>Untuk mencapai tujuan diatas, ada banyak cara. Aku memilih pakai <a href="http://nginx.org/en/docs/http/ngx_http_map_module.html">Module ngx_http_map_module</a> dan <a href="http://nginx.org/en/docs/http/ngx_http_geo_module.html">Module ngx_http_geo_module</a> karena menurutku lebih mudah dan fleksible.</p>
<p>Sehingga, config vhost nginx-nya menjadi:</p>
<pre data-lang="conf" style="background-color:#fcf0ca;color:#282828aa;" class="language-conf "><code class="language-conf" data-lang="conf"><span style="color:#282828;">geo </span><span style="color:#9d0006;">$auth</span><span> {
</span><span> </span><span style="color:#282828;">default </span><span style="color:#79740e;">"Restricted Area"</span><span>;
</span><span> </span><span style="color:#282828;">172</span><span style="color:#b23c15;">.</span><span style="color:#8f3f71;">16</span><span style="color:#b23c15;">.</span><span style="color:#8f3f71;">1</span><span style="color:#b23c15;">.</span><span style="color:#8f3f71;">0</span><span style="color:#b23c15;">/</span><span style="color:#8f3f71;">24 </span><span style="color:#79740e;">"off"</span><span>;
</span><span> </span><span style="color:#282828;">192</span><span style="color:#b23c15;">.</span><span style="color:#8f3f71;">168</span><span style="color:#b23c15;">.</span><span style="color:#8f3f71;">1</span><span style="color:#b23c15;">.</span><span style="color:#8f3f71;">0</span><span style="color:#b23c15;">/</span><span style="color:#8f3f71;">24 </span><span style="color:#79740e;">"off"</span><span>;
</span><span>}
</span><span>
</span><span>
</span><span style="color:#282828;">map </span><span style="color:#9d0006;">$request_uri $auth</span><span> {
</span><span> </span><span style="color:#282828;">default </span><span style="color:#79740e;">"Restricted Area"</span><span>;
</span><span> </span><span style="color:#79740e;">"/?webhook-author=sumar&notification-target=telegram" "off"</span><span>;
</span><span>}
</span><span>
</span><span style="color:#9d0006;">server </span><span>{
</span><span> </span><span style="color:#282828;">server_name </span><span>devel</span><span style="color:#b23c15;">.</span><span>internal</span><span style="color:#b23c15;">-</span><span>site</span><span style="color:#b23c15;">.</span><span>localdomain;
</span><span>
</span><span> </span><span style="color:#282828;">root </span><span style="color:#b23c15;">/</span><span>var</span><span style="color:#b23c15;">/</span><span>www</span><span style="color:#b23c15;">/</span><span>devel</span><span style="color:#b23c15;">.</span><span>internal</span><span style="color:#b23c15;">-</span><span>site</span><span style="color:#b23c15;">.</span><span>localdomain;
</span><span style="color:#9d0006;"> index</span><span> index</span><span style="color:#b23c15;">.</span><span>php;
</span><span>
</span><span> </span><span style="color:#282828;">access_log </span><span style="color:#b23c15;">/</span><span>var</span><span style="color:#b23c15;">/</span><span>log</span><span style="color:#b23c15;">/</span><span>nginx</span><span style="color:#b23c15;">/</span><span>devel</span><span style="color:#b23c15;">.</span><span>internal</span><span style="color:#b23c15;">-</span><span>site</span><span style="color:#b23c15;">.</span><span>localdomain</span><span style="color:#b23c15;">-</span><span>access</span><span style="color:#b23c15;">.</span><span>log;
</span><span> </span><span style="color:#282828;">error_log </span><span style="color:#b23c15;">/</span><span>var</span><span style="color:#b23c15;">/</span><span>log</span><span style="color:#b23c15;">/</span><span>nginx</span><span style="color:#b23c15;">/</span><span>devel</span><span style="color:#b23c15;">.</span><span>internal</span><span style="color:#b23c15;">-</span><span>site</span><span style="color:#b23c15;">.</span><span>localdomain</span><span style="color:#b23c15;">-</span><span>error</span><span style="color:#b23c15;">.</span><span>log;
</span><span>
</span><span style="color:#9d0006;"> location </span><span style="color:#b23c15;">/</span><span> {
</span><span> </span><span style="color:#282828;">try_files </span><span style="color:#9d0006;">$uri $uri</span><span style="color:#b23c15;">/ /</span><span>index</span><span style="color:#b23c15;">.</span><span>php</span><span style="color:#b23c15;">?</span><span style="color:#9d0006;">$args</span><span>;
</span><span>
</span><span> </span><span style="font-style:italic;color:#928374;"># basic auth on/off based on nginx map module
</span><span> </span><span style="color:#282828;">auth_basic </span><span style="color:#9d0006;">$auth</span><span>;
</span><span> </span><span style="color:#282828;">auth_basic_user_file </span><span style="color:#79740e;">"/etc/nginx/myhtpasswd"</span><span>;
</span><span> }
</span><span>
</span><span style="color:#9d0006;"> location </span><span style="color:#b23c15;">~ \.</span><span>php$ {
</span><span style="color:#9d0006;"> include </span><span style="color:#b57614;">snippets/fastcgi-php.conf</span><span>;
</span><span> </span><span style="color:#282828;">fastcgi_pass </span><span>unix</span><span style="color:#b23c15;">:/</span><span>var</span><span style="color:#b23c15;">/</span><span>run</span><span style="color:#b23c15;">/</span><span>php</span><span style="color:#b23c15;">/</span><span>php7</span><span style="color:#b23c15;">.</span><span style="color:#8f3f71;">4</span><span style="color:#b23c15;">-</span><span>fpm</span><span style="color:#b23c15;">.</span><span>sock;
</span><span> </span><span style="color:#282828;">fastcgi_param </span><span style="color:#b57614;">SCRIPT_FILENAME </span><span style="color:#9d0006;">$document_root$</span><span>fastcgi_script_name;
</span><span> }
</span><span>
</span><span>
</span><span> </span><span style="color:#282828;">listen </span><span style="color:#8f3f71;">443</span><span> ssl http2; </span><span style="font-style:italic;color:#928374;"># managed by Certbot
</span><span> </span><span style="color:#282828;">ssl_certificate </span><span style="color:#b23c15;">/</span><span>etc</span><span style="color:#b23c15;">/</span><span>letsencrypt</span><span style="color:#b23c15;">/</span><span>live</span><span style="color:#b23c15;">/</span><span>devel</span><span style="color:#b23c15;">.</span><span style="color:#b57614;">internal-site.localdomain/fullchain.pem</span><span>; </span><span style="font-style:italic;color:#928374;"># managed by Certbot
</span><span> </span><span style="color:#282828;">ssl_certificate_key </span><span style="color:#b23c15;">/</span><span>etc</span><span style="color:#b23c15;">/</span><span>letsencrypt</span><span style="color:#b23c15;">/</span><span>live</span><span style="color:#b23c15;">/</span><span>devel</span><span style="color:#b23c15;">.</span><span style="color:#b57614;">internal-site.localdomain/privkey.pem</span><span>; </span><span style="font-style:italic;color:#928374;"># managed by Certbot
</span><span style="color:#9d0006;"> include </span><span style="color:#b23c15;">/</span><span>etc</span><span style="color:#b23c15;">/</span><span>letsencrypt</span><span style="color:#b23c15;">/</span><span>options</span><span style="color:#b23c15;">-</span><span>ssl</span><span style="color:#b23c15;">-</span><span>nginx</span><span style="color:#b23c15;">.</span><span>conf; </span><span style="font-style:italic;color:#928374;"># managed by Certbot
</span><span> </span><span style="color:#282828;">ssl_dhparam </span><span style="color:#b23c15;">/</span><span>etc</span><span style="color:#b23c15;">/</span><span>letsencrypt</span><span style="color:#b23c15;">/</span><span>ssl</span><span style="color:#b23c15;">-</span><span>dhparams</span><span style="color:#b23c15;">.</span><span>pem; </span><span style="font-style:italic;color:#928374;"># managed by Certbot
</span><span>
</span><span style="color:#9d0006;"> location </span><span style="color:#b23c15;">~ /\.</span><span>(</span><span style="color:#b23c15;">?!</span><span>well</span><span style="color:#b23c15;">-</span><span>known)</span><span style="color:#b23c15;">.*</span><span> {
</span><span> </span><span style="color:#282828;">deny </span><span>all;
</span><span> }
</span><span>}
</span><span>
</span><span style="color:#9d0006;">server </span><span>{
</span><span style="color:#9d0006;"> if</span><span> (</span><span style="color:#9d0006;">$host </span><span style="color:#b23c15;">=</span><span> devel</span><span style="color:#b23c15;">.</span><span>internal</span><span style="color:#b23c15;">-</span><span>site</span><span style="color:#b23c15;">.</span><span>localdomain) {
</span><span> </span><span style="color:#282828;">return </span><span style="color:#8f3f71;">301 </span><span style="color:#282828;">https://$host$request_uri</span><span>;
</span><span> } </span><span style="font-style:italic;color:#928374;"># managed by Certbot
</span><span>
</span><span> </span><span style="color:#282828;">listen </span><span style="color:#8f3f71;">80</span><span>;
</span><span> </span><span style="color:#282828;">server_name </span><span>devel</span><span style="color:#b23c15;">.</span><span>internal</span><span style="color:#b23c15;">-</span><span>site</span><span style="color:#b23c15;">.</span><span>localdomain;
</span><span> </span><span style="color:#282828;">return </span><span style="color:#8f3f71;">404</span><span>; </span><span style="font-style:italic;color:#928374;"># managed by Certbot
</span><span>}
</span></code></pre>
<p>Done</p>
Nginx Return Custom Json
2021-11-14T18:34:20+07:00
2021-11-14T18:34:20+07:00
Unknown
https://www.sumarsono.com/nginx-return-custom-json/
<p>Nginx return custom json</p>
<pre data-lang="ini" style="background-color:#fcf0ca;color:#282828aa;" class="language-ini "><code class="language-ini" data-lang="ini"><span style="color:#9d0006;">server </span><span>{
</span><span> </span><span style="color:#282828;">listen </span><span style="color:#8f3f71;">80</span><span> default_server;
</span><span> </span><span style="color:#282828;">server_name </span><span style="color:#b57614;">_</span><span>;
</span><span>
</span><span> </span><span style="color:#282828;">root </span><span style="color:#b23c15;">/</span><span>var</span><span style="color:#b23c15;">/</span><span>www</span><span style="color:#b23c15;">/</span><span>html;
</span><span style="color:#9d0006;"> index</span><span> index</span><span style="color:#b23c15;">.</span><span>html;
</span><span>
</span><span style="color:#9d0006;"> location </span><span style="color:#b23c15;">/</span><span> {
</span><span> </span><span style="color:#282828;">default_type </span><span style="color:#b57614;">application/json</span><span>;
</span><span> </span><span style="color:#282828;">return </span><span style="color:#8f3f71;">200 </span><span style="color:#79740e;">'{"code":"0", "message": "I am alive"}'</span><span>;
</span><span> }
</span><span>}
</span></code></pre>
<p>Test:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">▶ curl -iL anuku.domainku.tld
</span><span style="color:#282828;">HTTP/1.1 200 OK
</span><span style="color:#282828;">Server: nginx/1.18.0 (Ubuntu</span><span>)
</span><span style="color:#282828;">Date: Sun, 14 Nov 2021 11:39:17 GMT
</span><span style="color:#282828;">Content-Type: application/json
</span><span style="color:#282828;">Content-Length: 37
</span><span style="color:#282828;">Connection: keep-alive
</span><span style="color:#282828;">Vary: Accept-Encoding
</span><span>
</span><span style="color:#282828;">{</span><span style="color:#79740e;">"code"</span><span style="color:#282828;">:</span><span style="color:#79740e;">"0"</span><span style="color:#282828;">, </span><span style="color:#79740e;">"message"</span><span style="color:#282828;">: </span><span style="color:#79740e;">"I am alive"</span><span>}</span><span style="color:#282828;">%
</span></code></pre>
Limit Sudoer Command
2021-11-14T08:35:54+07:00
2021-11-14T08:35:54+07:00
Unknown
https://www.sumarsono.com/limit-sudoer-command/
<p>Allow <code>deployer</code> to exec supervisorctl only</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">deployer ALL=(ALL</span><span>) !</span><span style="color:#282828;">ALL
</span><span style="color:#282828;">deployer ALL=NOPASSWD: /usr/bin/supervisorctl
</span></code></pre>
Aws SES Whitelist Ip Address
2021-11-14T08:30:25+07:00
2021-11-14T08:30:25+07:00
Unknown
https://www.sumarsono.com/aws-ses-whitelist-ip-address/
<pre data-lang="json" style="background-color:#fcf0ca;color:#282828aa;" class="language-json "><code class="language-json" data-lang="json"><span>{
</span><span> </span><span style="color:#79740e;">"Version"</span><span>: </span><span style="color:#79740e;">"2021-11-14"</span><span>,
</span><span> </span><span style="color:#79740e;">"Statement"</span><span>: [
</span><span> {
</span><span> </span><span style="color:#79740e;">"Sid"</span><span>: </span><span style="color:#79740e;">"VisualEditor0"</span><span>,
</span><span> </span><span style="color:#79740e;">"Effect"</span><span>: </span><span style="color:#79740e;">"Allow"</span><span>,
</span><span> </span><span style="color:#79740e;">"Action"</span><span>: </span><span style="color:#79740e;">"ses:SendRawEmail"</span><span>,
</span><span> </span><span style="color:#79740e;">"Resource"</span><span>: </span><span style="color:#79740e;">"*"</span><span>,
</span><span> </span><span style="color:#79740e;">"Condition"</span><span>: {
</span><span> </span><span style="color:#79740e;">"ForAnyValue:IpAddress"</span><span>: {
</span><span> </span><span style="color:#79740e;">"aws:SourceIp"</span><span>: [
</span><span> </span><span style="color:#79740e;">"aa.bb.cc.dd/32"</span><span>,
</span><span> </span><span style="color:#79740e;">"aa.bb.xx.yy/32"
</span><span> ]
</span><span> }
</span><span> }
</span><span> }
</span><span> ]
</span><span>}
</span></code></pre>
Install Hugo Macos
2021-11-14T08:11:32+07:00
2021-11-14T08:11:32+07:00
Unknown
https://www.sumarsono.com/install-hugo-macos/
<p>Cara install hugo di macOS:</p>
<ul>
<li>
<p>Download binary hugo dari <a href="https://github.com/gohugoio/hugo/releases">halaman release hugo</a> ,pilih yang ada embel-embel <em>MacOS</em></p>
</li>
<li>
<p>Ekstrak hasil download-nya.</p>
</li>
<li>
<p>Pindahkan binary hugo dari hasil ekstrak ke $PATH MacOS, kalau aku pakai custom PATH di <code>/Users/sumar/.local/bin</code> sehingga aku punya export PATH di <code>.zshrc</code>:</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="font-style:italic;color:#928374;"># Add localPath
</span><span style="color:#9d0006;">export </span><span style="color:#282828;">PATH</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">$</span><span style="color:#282828;">PATH</span><span style="color:#79740e;">:/Users/sumar/.local/bin
</span></code></pre>
</li>
<li>
<p>Untuk menjalankan hugo, cukup buka ulang terminal atau source ke .zshrc</p>
</li>
</ul>
Kombinasi Wireguard Dan Adguardhome
2021-09-09T11:45:17+07:00
2021-09-09T11:45:17+07:00
Unknown
https://www.sumarsono.com/kombinasi-wireguard-dan-adguardhome/
<p>Mari kita kombinasikan wireguard dengan AdguardHome, biar dapat VPN dengan addon adsblock.
Wireguard sebagai VPN, AdguardHome sebagai adblocker. Lebih praktis lagi, aku pakai docker. Untuk wireguard, aku mau pakai docker image <a href="https://github.com/WeeJeWel/wg-easy">wg-easy</a>, ia include webui utk manage wireguard-nya. Untuk adguardhome aku pakai <a href="https://hub.docker.com/r/adguard/adguardhome">image official</a>.</p>
<p>Syarat sistem:</p>
<ul>
<li>Terpasang Distro Linux (Aku pakai Debian 10)</li>
<li>Terpasang Kernel dengan dukungan wireguard</li>
<li>Terpasang Docker dan Docker Compose</li>
</ul>
<p>Langkah-langkah:</p>
<ul>
<li>SSH ke server</li>
<li>Bikin direktori wg-easy, dan masuk kedalamnya</li>
<li>Bikin docker-compose.yaml, snipset docker-compose.yaml:</li>
</ul>
<pre data-lang="yaml" style="background-color:#fcf0ca;color:#282828aa;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span style="font-weight:bold;color:#407959;">version</span><span>: </span><span style="color:#79740e;">"3.5"
</span><span>
</span><span style="font-weight:bold;color:#407959;">networks</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">private_network</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">ipam</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">driver</span><span>: </span><span style="color:#79740e;">default
</span><span> </span><span style="font-weight:bold;color:#407959;">config</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">subnet</span><span>: </span><span style="color:#79740e;">10.2.0.0/24
</span><span>
</span><span style="font-weight:bold;color:#407959;">services</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">adguardhome</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">container_name</span><span>: </span><span style="color:#79740e;">adguardhome
</span><span> </span><span style="font-weight:bold;color:#407959;">image</span><span>: </span><span style="color:#79740e;">adguard/adguardhome
</span><span> </span><span style="font-weight:bold;color:#407959;">restart</span><span>: </span><span style="color:#79740e;">unless-stopped
</span><span> </span><span style="font-weight:bold;color:#407959;">hostname</span><span>: </span><span style="color:#79740e;">adguardhome
</span><span> </span><span style="font-weight:bold;color:#407959;">dns</span><span>:
</span><span> - </span><span style="color:#8f3f71;">127.0.0.1
</span><span> - </span><span style="color:#8f3f71;">8.8.8.8
</span><span> </span><span style="font-weight:bold;color:#407959;">environment</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">TZ</span><span>: </span><span style="color:#79740e;">"Asia/Jakarta"
</span><span> </span><span style="font-weight:bold;color:#407959;">volumes</span><span>:
</span><span> - </span><span style="color:#79740e;">./adguardhome/work:/opt/adguardhome/work
</span><span> - </span><span style="color:#79740e;">./adguardhome/conf:/opt/adguardhome/conf
</span><span> </span><span style="font-weight:bold;color:#407959;">cap_add</span><span>:
</span><span> - </span><span style="color:#79740e;">NET_ADMIN
</span><span> </span><span style="font-weight:bold;color:#407959;">networks</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">private_network</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">ipv4_address</span><span>: </span><span style="color:#8f3f71;">10.2.0.99
</span><span>
</span><span> </span><span style="font-weight:bold;color:#407959;">wireguard</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">depends_on</span><span>:
</span><span> - </span><span style="color:#79740e;">adguardhome
</span><span> </span><span style="font-weight:bold;color:#407959;">container_name</span><span>: </span><span style="color:#79740e;">wg-easy
</span><span> </span><span style="font-weight:bold;color:#407959;">image</span><span>: </span><span style="color:#79740e;">weejewel/wg-easy
</span><span> </span><span style="font-weight:bold;color:#407959;">restart</span><span>: </span><span style="color:#79740e;">unless-stopped
</span><span> </span><span style="font-weight:bold;color:#407959;">hostname</span><span>: </span><span style="color:#79740e;">wg-easy
</span><span> </span><span style="font-weight:bold;color:#407959;">cap_add</span><span>:
</span><span> - </span><span style="color:#79740e;">NET_ADMIN
</span><span> - </span><span style="color:#79740e;">SYS_MODULE
</span><span> </span><span style="font-weight:bold;color:#407959;">environment</span><span>:
</span><span> - </span><span style="color:#79740e;">WG_HOST=xx.xx.xx.xx </span><span style="font-style:italic;color:#928374;"># masukan IP publikmu disini, wajib!
</span><span> - </span><span style="color:#79740e;">PASSWORD=password </span><span style="font-style:italic;color:#928374;"># masukan password wg web ui dsini, wajib!
</span><span> - </span><span style="color:#79740e;">WG_PORT=51820
</span><span> - </span><span style="color:#79740e;">WG_DEFAULT_ADDRESS=10.8.0.x
</span><span> - </span><span style="color:#79740e;">WG_DEFAULT_DNS=10.2.0.99
</span><span> </span><span style="font-weight:bold;color:#407959;">volumes</span><span>:
</span><span> - </span><span style="color:#79740e;">/lib/modules:/lib/modules
</span><span> - </span><span style="color:#79740e;">.:/etc/wireguard
</span><span> </span><span style="font-weight:bold;color:#407959;">ports</span><span>:
</span><span> - </span><span style="color:#79740e;">"51820:51820/udp"
</span><span> - </span><span style="color:#79740e;">"51821:51821/tcp"
</span><span> </span><span style="font-weight:bold;color:#407959;">sysctls</span><span>:
</span><span> - </span><span style="color:#79740e;">net.ipv4.conf.all.src_valid_mark=1
</span><span> - </span><span style="color:#79740e;">net.ipv4.ip_forward=1
</span><span> </span><span style="font-weight:bold;color:#407959;">networks</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">private_network</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">ipv4_address</span><span>: </span><span style="color:#8f3f71;">10.2.0.101
</span></code></pre>
<ul>
<li>dari dalam folder wg-easy, jalankan:</li>
</ul>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">docker-compose up -d
</span></code></pre>
<ul>
<li>pergi ke http://ip-public-mu:51821 kemudian bikin wg-profile utk klien</li>
<li>hubungkan klien ke wg-profile tersebut, kemudian dari klien ini kunjungi http://10.2.0.99:3000 dan selesaikan wizard instalasi adguard-home</li>
<li>seleasi</li>
</ul>
<p>Cool~</p>
Compile Hugo Extended Version on Termux
2021-06-22T12:54:11+07:00
2021-06-22T12:54:11+07:00
Unknown
https://www.sumarsono.com/compile-hugo-extended-version-on-termux/
<p>Sampai tulisan ini ditulis, hugo-extended version belum ada untuk versi arm64 di github release hugo. Oleh sebab itu aku harus compile sendiri, caranya cukup mudah karena tertulis di README.md repository hugo di github.</p>
<p>Berikut ini ringkasan cara compile hugo extended version di termux yang aku coba:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">$ git clone https://github.com/gohugoio/hugo.git
</span><span style="color:#282828;">$ cd hugo/
</span><span style="color:#282828;">$ CGO_ENABLED=1 go build --tags extended
</span><span style="color:#282828;">$ install hugo $PREFIX/bin/
</span><span style="color:#282828;">$ which hugo
</span><span style="color:#282828;">$ hugo version
</span><span style="color:#282828;">hugo v0.85.0-DEV+extended android/arm64 BuildDate=unknown
</span></code></pre>
Compile Cloudflared on Termux
2021-06-22T07:36:02+07:00
2021-06-22T07:36:02+07:00
Unknown
https://www.sumarsono.com/compile-cloudflared-on-termux/
<p>Cara mudah compile <code>cloudflared</code> di termux.</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">$ pkg install git make debianutils golang
</span><span style="color:#282828;">$ git clone https://github.com/cloudflare/cloudflared.git --depth</span><span style="color:#b23c15;">=</span><span style="color:#282828;">1
</span><span style="color:#282828;">$ sed -i </span><span style="color:#79740e;">'s/linux/android/g'</span><span style="color:#282828;"> Makefile
</span><span style="color:#282828;">$ install cloudflared $PREFIX/bin/cf
</span><span style="color:#282828;">$ which cf
</span></code></pre>
<p>Cloudflared siap digunakan di termux.</p>
Lxd Set Static Ip Container
2021-06-07T14:47:51+07:00
2021-06-07T14:47:51+07:00
Unknown
https://www.sumarsono.com/lxd-set-static-ip-container/
<p>Cara cepat set static ip address untuk kontainer lxd/lxc</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">lxc stop nama-kontainer
</span><span style="color:#282828;">lxc config device add nama-kontainer eth0 nic name=eth0 nictype=bridged parent=lxdbr0
</span><span style="color:#282828;">lxc config device set nama-kontainer eth0 ipv4.address 10.112.133.200
</span><span style="color:#282828;">lxc start nama-kontainer
</span></code></pre>
Hugo Dan Argo Tunnel Dalam Termux Bawa Blogmu Dalam Saku
2021-05-17T12:04:58+07:00
2021-05-17T12:04:58+07:00
Unknown
https://www.sumarsono.com/hugo-dan-argo-tunnel-dalam-termux-bawa-blogmu-dalam-saku/
<p>Mayoritas HP android selalu online 24 jam non stop layaknya server yang online terus-menerus. Sekarang, bayangkan seandainya kamu bisa jalanin <code>hugo server</code> di HP mu. Kemudian kamu jalanin <code>cloudflare argo tunnel</code> untuk ekspose hugo server tersebut ke internet 24 Jam non stop, keren ya.</p>
<p>Apakah memungkinkan? Sangat memungkinkan, mari kita cek:</p>
<ol>
<li>Kita butuh Hugo, ia ada di repo termux.</li>
<li>Kita butuh Cloudflared, binary utk argo tunnel, ia tidak ada di repo termux, tapi kita bisa build binary-nya dengan mudah. Mereka menyediakan Makefile untuk build binary cloudflared.</li>
<li>Kita butuh termux, silakan ambil dari repo fdroid.</li>
<li>Kita tidak butuh root, mantap jiwa.</li>
</ol>
<h2 id="ringkasan-step-by-step-setup-hugo-dan-cloudflared-di-termux">Ringkasan step by step setup Hugo dan cloudflared di termux</h2>
<p>Pertama buka termux session 1</p>
<p>Kedua, install app yg dibutuhkan</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">$ pkg update
</span><span style="color:#282828;">$ pkg upgrade
</span><span style="color:#282828;">$ pkg install hugo vim golang wget curl git proot resolv-conf make debianutils
</span></code></pre>
<p>selanjutnya, bikin blog Hugo</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">$ hugo new site konvolusi.ml
</span><span style="color:#282828;">$ cd konvolusi.ml
</span><span style="color:#282828;">$ hugo server
</span><span>
</span><span style="color:#282828;">...
</span><span style="color:#282828;">Running in Fast Render Mode. For full rebuilds on change: hugo server --disableFastRender
</span><span style="color:#282828;">Web Server is available at http://localhost:1313/ (bind address 127.0.0.1</span><span>)
</span><span style="color:#282828;">Press Ctrl+C to stop
</span></code></pre>
<p>Akan muncul URL untuk akses blog yang barusan dibuat, default ada di http://localhost:1313/, bisa diakses dari browser HP.</p>
<p>Ketiga, aku mau ekspose ke internet, aku butuh argo tunnel, maka aku compile cloudflared, buat session baru di termux sehingga sekarang ada session 1 yg jalanin <code>hugo server</code> dan session 2 untuk setup Cloudflared, pada jendela session 2 termux jalankan:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">$ cd ~
</span><span style="color:#282828;">$ git clone https://github.com/cloudflare/cloudflared.git --depth</span><span style="color:#b23c15;">=</span><span style="color:#282828;">1
</span><span>
</span><span style="color:#282828;">$ cd cloudflared
</span><span style="color:#282828;">$ sed -i </span><span style="color:#79740e;">'s/linux/android/g'</span><span style="color:#282828;"> Makefile
</span><span>
</span><span style="color:#282828;">$ make cloudflared
</span><span style="color:#282828;">$ install cloudflared /data/data/com.termux/files/usr/bin
</span></code></pre>
<p>Keempat, setup Cloudflared</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">$ cloudflared tunnel login
</span><span style="color:#282828;">$ cloudflared tunnel create konvolusi
</span></code></pre>
<p>Kita akan mendapatkan argo tunnel id dan lokasi sertifikat argo tunnel, selanjutnya bikin config yg aku sebut <code>konvolusi.yml</code></p>
<pre data-lang="yaml" style="background-color:#fcf0ca;color:#282828aa;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span style="font-weight:bold;color:#407959;">credentials-file</span><span>: </span><span style="color:#79740e;">/data/data/com.termux/files/home/.cloudflared/long-id.json
</span><span style="font-weight:bold;color:#407959;">tunnel</span><span>: </span><span style="color:#79740e;">long-id
</span><span>
</span><span style="font-weight:bold;color:#407959;">ingress</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">hostname</span><span>: </span><span style="color:#79740e;">konvolusi.ml
</span><span> </span><span style="font-weight:bold;color:#407959;">service</span><span>: </span><span style="color:#79740e;">http://127.0.0.1:1313
</span><span> - </span><span style="font-weight:bold;color:#407959;">service</span><span>: </span><span style="color:#79740e;">http_status:404
</span></code></pre>
<p>Next, bikin DNS record utk konvolusi.ml</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">$ cloudflared tunnel route dns long-id konvolusi.ml
</span></code></pre>
<p>Saatnya expose ke internet</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">$ proot -b $PREFIX/etc/resolv.conf:/etc/resolv.conf cloudflared tunnel --config konvolusi.yml run
</span></code></pre>
<p>Dengan demikian maka hugo server di hp bisa aku akses dari internet lewat https://konvolusi.ml</p>
<p>Apa yang kita jalankan di termux akan terus berjalan selama kita tidak kill termux.</p>
<p>Referensi:</p>
<ol>
<li>https://sumarsono.com/expose-local-lxd-container-ke-internet-pakai-cloudflare-argo-tunnel/</li>
<li>https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/installation</li>
<li>https://gist.github.com/Erisa/4015ae12211434b8f2f64ac1d731b830</li>
<li>https://stackoverflow.com/a/63915298</li>
</ol>
Refleksi Idulfitri 1442H
2021-05-17T00:44:19+07:00
2021-05-17T00:44:19+07:00
Unknown
https://www.sumarsono.com/refleksi-idulfitri-1442h/
<p>Idulfitri tahun 1442H menjadi idulfitri yang sangat spesial untukku.</p>
<p>Idulfitri kali ini, aku sudah punya istri, dan istriku sedang hamil 2 bulan. Benar-benar mendebarkan bahagia. Rasanya aku tidak sabar untuk idulfitri tahun depan, kami punya momongan!</p>
<p>Itu sangat membahagiakan, sungguh!</p>
<p>Teman-teman, doakan kami ya semoga kami selalu sehat dan bahagia. Terutama untuk istriku dan anak yang dikandungnya. Semoga kami dikaruniai anak yang sehat jasmani dan rohaninya.</p>
<p>"Ya Tuhanku, berilah aku dari sisi Engkau seorang anak yang baik. Sesungguhnya Engkau Maha Pendengar doa." (QS Ali Imran: 38)</p>
Install Ghost Blogging Platform Di Ubuntu 20.04 Focal Fossa
2021-05-11T13:44:34+07:00
2021-05-11T13:44:34+07:00
Unknown
https://www.sumarsono.com/install-ghost-blogging-platform-di-ubuntu-2004-focal-fossa/
<blockquote>
<p>Ghost is a free and open source blogging platform written in JavaScript and distributed under the MIT License, designed to simplify the process of online publishing for individual bloggers as well as online publications. <a href="https://en.wikipedia.org/wiki/Ghost_(blogging_platform)">Wikipedia</a></p>
</blockquote>
<p>Aku akan memakai kontainer ubuntu 20.04 untuk dipasang Ghost. Pertama, aku bikin dulu kontainer-nya dengan nama ghost dan base image ubuntu/focal</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">┌─[sumar][tingpret][~]
</span><span style="color:#282828;">└─▪ lxc launch images:ubuntu/focal ghost
</span><span style="color:#282828;">Creating ghost
</span><span style="color:#282828;">Starting ghost
</span></code></pre>
<p>Kemudian aku akan exec shell ke dalam kontainer ghost</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">┌─[sumar][tingpret][~]
</span><span style="color:#282828;">└─▪ lxc exec ghost</span><span style="color:#b23c15;"> --</span><span style="color:#282828;"> bash
</span><span style="color:#282828;">root@ghost:~#
</span></code></pre>
<p>Dari dalam kontainer ghost, aku akan bikin user baru bernama <code>sumar</code> kemudian install <code>nginx</code> dan <code>curl</code></p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">┌─[sumar][tingpret][~]
</span><span style="color:#282828;">└─▪ lxc exec ghost</span><span style="color:#b23c15;"> --</span><span style="color:#282828;"> bash
</span><span style="color:#282828;">root@ghost:~# apt update
</span><span>
</span><span style="color:#282828;">root@ghost:~# adduser sumar
</span><span style="color:#282828;">Adding user `sumar</span><span style="color:#79740e;">' ...
</span><span style="color:#79740e;">Adding new group `sumar'</span><span style="color:#282828;"> (1001) ...
</span><span style="color:#282828;">Adding new user `sumar</span><span style="color:#79740e;">' (1001) with group `sumar'</span><span style="color:#282828;"> ...
</span><span style="color:#282828;">Creating home directory `/home/sumar</span><span style="color:#79740e;">' ...
</span><span style="color:#79740e;">Copying files from `/etc/skel'</span><span style="color:#282828;"> ...
</span><span style="color:#282828;">New password:
</span><span style="color:#282828;">Retype new password:
</span><span style="color:#282828;">passwd: password updated successfully
</span><span style="color:#282828;">Changing the user information for sumar
</span><span style="color:#282828;">Enter the new value, or press ENTER for the default
</span><span style="color:#282828;"> Full Name </span><span style="color:#9d0006;">[]</span><span style="color:#282828;">: Sumarsono
</span><span style="color:#282828;"> Room Number </span><span style="color:#9d0006;">[]</span><span style="color:#282828;">:
</span><span style="color:#282828;"> Work Phone </span><span style="color:#9d0006;">[]</span><span style="color:#282828;">:
</span><span style="color:#282828;"> Home Phone </span><span style="color:#9d0006;">[]</span><span style="color:#282828;">:
</span><span style="color:#282828;"> Other </span><span style="color:#9d0006;">[]</span><span style="color:#282828;">:
</span><span style="color:#282828;">Is the information correct</span><span style="color:#b23c15;">? </span><span style="color:#9d0006;">[</span><span style="color:#282828;">Y/n</span><span style="color:#9d0006;">]</span><span style="color:#282828;"> Y
</span><span style="color:#282828;">
</span><span style="color:#282828;">root@ghost:~# usermod -aG sudo sumar
</span><span style="color:#282828;">
</span><span style="color:#282828;">root@ghost:~# su - sumar
</span><span style="color:#282828;">To run a command as administrator (user </span><span style="color:#79740e;">"root"</span><span style="color:#282828;">), use </span><span style="color:#79740e;">"sudo <command>"</span><span style="color:#282828;">.
</span><span style="color:#282828;">See </span><span style="color:#79740e;">"man sudo_root"</span><span style="color:#282828;"> for details.
</span><span style="color:#282828;">
</span><span style="color:#282828;">sumar@ghost:~$ sudo apt-get install nginx curl
</span><span style="color:#282828;">[sudo] password for sumar:
</span><span style="color:#282828;">...
</span><span style="color:#282828;">Do you want to continue</span><span style="color:#b23c15;">? </span><span style="color:#9d0006;">[</span><span style="color:#282828;">Y/n</span><span style="color:#9d0006;">]</span><span style="color:#282828;"> y
</span><span style="color:#282828;">
</span></code></pre>
<p>Selanjutnya, aku akan pasang nodejs versi 14 yang dibutuhkan oleh ghost, dilanjutkan dengan memasang ghost-cli pakai npm</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">sumar@ghost:~$ curl -sL https://deb.nodesource.com/setup_14.x </span><span style="color:#b23c15;">| </span><span style="color:#282828;">sudo -E bash
</span><span>
</span><span style="color:#282828;">sumar@ghost:~$ sudo apt-get install -y nodejs
</span><span>
</span><span style="color:#282828;">sumar@ghost:~$ sudo npm install ghost-cli@latest -g
</span><span>
</span></code></pre>
<p>Lanjut, saatnya bikin website pakai ghost-cli, dimulai dari menyiapkan direktori hingga setup-nya. Wizard <code>ghost install</code> ini sangat mudah untuk diikuti, baca aca instruksinya dan ikuti.</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">sumar@ghost:~$ sudo mkdir -p /var/www/ghost.sumarsono.com
</span><span style="color:#282828;">sumar@ghost:~$ sudo chown sumar:sumar /var/www/ghost.sumarsono.com
</span><span style="color:#282828;">sumar@ghost:~$ sudo chmod 755 /var/www/ghost.sumarsono.com
</span><span style="color:#282828;">sumar@ghost:~$ cd /var/www/ghost.sumarsono.com
</span><span style="color:#282828;">sumar@ghost:/var/www/ghost.sumarsono.com$ ghost install
</span><span style="color:#282828;">✔ Checking system Node.js version - found v14.16.1
</span><span style="color:#282828;">✔ Checking logged in user
</span><span style="color:#282828;">✔ Checking current folder permissions
</span><span style="color:#282828;">✔ Checking system compatibility
</span><span style="color:#282828;">Local MySQL install was not found or is stopped. You can ignore this if you are using a remote MySQL host.
</span><span style="color:#282828;">Alternatively you could:
</span><span style="color:#282828;">a</span><span>) </span><span style="color:#282828;">install/start MySQL locally
</span><span style="color:#282828;">b</span><span>) </span><span style="color:#282828;">run `ghost install --db</span><span style="color:#b23c15;">=</span><span style="color:#282828;">sqlite3` to use sqlite
</span><span style="color:#282828;">c</span><span>) </span><span style="color:#282828;">run `ghost install local` to get a development install using sqlite3.
</span><span style="color:#282828;">? Continue anyway</span><span style="color:#b23c15;">?</span><span style="color:#282828;"> Yes
</span><span style="color:#282828;">MySQL check skipped
</span><span style="color:#282828;">ℹ Checking for a MySQL installation </span><span style="color:#9d0006;">[</span><span style="color:#282828;">skipped</span><span style="color:#9d0006;">]
</span><span style="color:#282828;">✔ Checking memory availability
</span><span style="color:#282828;">✔ Checking free space
</span><span style="color:#282828;">✔ Checking for latest Ghost version
</span><span style="color:#282828;">✔ Setting up install directory
</span><span style="color:#282828;">✔ Downloading and installing Ghost v4.4.0
</span><span style="color:#282828;">✔ Finishing install process
</span><span style="color:#282828;">? Enter your blog URL: http://ghost.sumarsono.com
</span><span style="color:#282828;">? Enter your MySQL hostname: 10.179.72.186
</span><span style="color:#282828;">? Enter your MySQL username: </span><span style="color:#9d0006;">[</span><span style="color:#282828;">hidden</span><span style="color:#9d0006;">]
</span><span style="color:#282828;">? Enter your MySQL password: </span><span style="color:#9d0006;">[</span><span style="color:#282828;">hidden</span><span style="color:#9d0006;">]
</span><span style="color:#282828;">? Enter your Ghost database name: </span><span style="color:#9d0006;">[</span><span style="color:#282828;">hidden</span><span style="color:#9d0006;">]
</span><span style="color:#282828;">✔ Configuring Ghost
</span><span style="color:#282828;">✔ Setting up instance
</span><span style="color:#282828;">+ sudo useradd --system --user-group ghost
</span><span style="color:#282828;">+ sudo chown -R ghost:ghost /var/www/ghost.sumarsono.com/content
</span><span style="color:#282828;">✔ Setting up </span><span style="color:#79740e;">"ghost"</span><span style="color:#282828;"> system user
</span><span style="color:#282828;">ℹ Setting up </span><span style="color:#79740e;">"ghost"</span><span style="color:#282828;"> mysql user </span><span style="color:#9d0006;">[</span><span style="color:#282828;">skipped</span><span style="color:#9d0006;">]
</span><span style="color:#282828;">? Do you wish to set up Nginx</span><span style="color:#b23c15;">?</span><span style="color:#282828;"> Yes
</span><span style="color:#282828;">+ sudo mv /tmp/ghost-sumarsono-com/ghost.sumarsono.com.conf /etc/nginx/sites-available/ghost.sumarsono.com.conf
</span><span style="color:#282828;">+ sudo ln -sf /etc/nginx/sites-available/ghost.sumarsono.com.conf /etc/nginx/sites-enabled/ghost.sumarsono.com.conf
</span><span style="color:#282828;">+ sudo nginx -s reload
</span><span style="color:#282828;">✔ Setting up Nginx
</span><span style="color:#282828;">? Do you wish to set up SSL</span><span style="color:#b23c15;">?</span><span style="color:#282828;"> No
</span><span style="color:#282828;">ℹ Setting up SSL </span><span style="color:#9d0006;">[</span><span style="color:#282828;">skipped</span><span style="color:#9d0006;">]
</span><span style="color:#282828;">? Do you wish to set up Systemd</span><span style="color:#b23c15;">?</span><span style="color:#282828;"> Yes
</span><span style="color:#282828;">+ sudo mv /tmp/ghost-sumarsono-com/ghost_ghost-sumarsono-com.service /lib/systemd/system/ghost_ghost-sumarsono-com.service
</span><span style="color:#282828;">+ sudo systemctl daemon-reload
</span><span style="color:#282828;">✔ Setting up Systemd
</span><span style="color:#282828;">+ sudo systemctl is-active ghost_ghost-sumarsono-com
</span><span style="color:#282828;">? Do you want to start Ghost</span><span style="color:#b23c15;">?</span><span style="color:#282828;"> Yes
</span><span style="color:#282828;">+ sudo systemctl start ghost_ghost-sumarsono-com
</span><span style="color:#282828;">+ sudo systemctl is-enabled ghost_ghost-sumarsono-com
</span><span style="color:#282828;">+ sudo systemctl enable ghost_ghost-sumarsono-com --quiet
</span><span style="color:#282828;">✔ Starting Ghost
</span><span>
</span><span style="color:#282828;">Ghost uses direct mail by default. To set up an alternative email method read our docs at https://ghost.org/docs/config/#mail
</span><span>
</span><span style="color:#282828;">------------------------------------------------------------------------------
</span><span>
</span><span style="color:#282828;">Ghost was installed successfully! To complete setup of your publication, visit:
</span><span>
</span><span> </span><span style="color:#282828;">http://ghost.sumarsono.com/ghost/
</span><span>
</span></code></pre>
<p>Tinggal publish ghost.sumarsono.com via argi tunnel</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">┌─[sumar][tingpret][~]
</span><span style="color:#282828;">└─▪ cat /etc/cloudflared/config.yml
</span><span style="color:#282828;">credentials-file: </span><span style="color:#9d0006;">[</span><span style="color:#282828;">hidden</span><span style="color:#9d0006;">]
</span><span style="color:#282828;">tunnel: </span><span style="color:#9d0006;">[</span><span style="color:#282828;">hidden</span><span style="color:#9d0006;">]
</span><span style="color:#282828;">loglevel: error
</span><span>
</span><span style="color:#282828;">ingress:
</span><span> </span><span style="color:#282828;">- hostname: ghost.sumarsono.com
</span><span> </span><span style="color:#282828;">service: http://10.179.72.146:80
</span></code></pre>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">┌─[sumar][tingpret][~]
</span><span style="color:#282828;">└─▪ cloudflared tunnel route dns </span><span style="color:#9d0006;">[</span><span style="color:#282828;">hidden</span><span style="color:#9d0006;">]</span><span style="color:#282828;"> ghost.sumarsono.com
</span><span>
</span></code></pre>
<p>Kalau bingung soal argo tunnel, bisa baca <a href="https://sumarsono.com/expose-local-lxd-container-ke-internet-pakai-cloudflare-argo-tunnel/">Expose Local Lxd Container Ke Internet Pakai Cloudflare Argo Tunnel</a></p>
<p>SELESAI, sekarang akses http://ghost.sumarsono.com/ghost/ dan selesaikan instalasi ghost-nya.</p>
Expose Local Lxd Container Ke Internet Pakai Cloudflare Argo Tunnel
2021-05-10T13:27:07+07:00
2021-05-10T13:27:07+07:00
Unknown
https://www.sumarsono.com/expose-local-lxd-container-ke-internet-pakai-cloudflare-argo-tunnel/
<p>Smart Routing, Cloudflare’s traffic acceleration feature. Starting today, we’re excited to announce that any organization can use the secure, outbound-only connection feature of the product <strong>at no cost</strong>. You can still add the paid Argo Smart Routing feature to accelerate traffic.</p>
<p>Sumber: <a href="https://blog.cloudflare.com/tunnel-for-everyone/">A Boring Announcement: Free Tunnels for Everyone</a></p>
<p>Kabar gembira tentunya, untuk aku dan kalian yang butuh Argo Tunnel. Argo tunnel bisa kita pakai untuk ekspose service lokal ke internet. Gampangnya gini:</p>
<p>Aku bikin web app, aku jalanin app tsb di laptopku, aku pengen temenku yang beda pulau untuk melihat app-ku dan menjajalnya. Mau di taruh di hosting kok gk menguntungkan orang cobanya cuma 1-2 jam, app-nya juga baru setengah jadi. Salah satu cara untuk ekspose aplikasi ku ke internet adalah pakai argo tunnel, nanti temenku bisa buka app-ku via appku.sumarsono.com misalnya.</p>
<p>Begitu kira-kira.</p>
<p>Namun, dalam kasus sekarang aku mau expose adguard yang ada di dalam kontainer lxc/lxd, supaya flow-nya lebih kelihatan.</p>
<h2 id="pertama-taruh-domain-di-cloudflare">Pertama, taruh domain di cloudflare</h2>
<p>Syarat mutlak untuk pakai Argo Tunnel. Domain yang akan kita pakai harus pakai nameserver cloudflare, di manage di cloudflare. Free juga kok, tenang.</p>
<h2 id="kedua-install-cloudflared">Kedua, install cloudflared</h2>
<p>Silakan ikuti petuah <a href="https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup">di dokumentasi official</a>. lebih jos. Aku pribadi memilih run compiled binary yang mereka sediakan. Tinggal download dan jalankan.</p>
<h2 id="ketiga-login-cloudflared">Ketiga, login cloudflared</h2>
<p>Cukup jalanin command di terminal</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">┌─[sumar][tingpret][~/opt]
</span><span style="color:#282828;">└─▪ cloudflared tunnel login
</span><span style="color:#282828;">A browser window should have opened at the following URL:
</span><span>
</span><span style="color:#282828;">https://dash.cloudflare.com/argotunnel?xxxyyyzzzdst
</span><span>
</span><span style="color:#282828;">If the browser failed to open, please visit the URL above directly in your browser.
</span><span style="color:#282828;">You have successfully logged in.
</span><span style="color:#282828;">If you wish to copy your credentials to a server, they have been saved to:
</span><span style="color:#282828;">/home/sumar/.cloudflared/cert.pem
</span></code></pre>
<p>Lalu ikuti wizard-nya.</p>
<h2 id="keempat-bikin-argo-tunnel">Keempat, bikin argo tunnel</h2>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">┌─[sumar][tingpret][~/opt]
</span><span style="color:#282828;">└─▪ cloudflared tunnel create lxd-adguard
</span><span style="color:#282828;">Tunnel credentials written to /home/sumar/.cloudflared/xxx-yyy-zzz-aaa-bbb.json. cloudflared chose this file based on where your origin certificate was found. Keep this file secret. To revoke these credentials, delete the tunnel.
</span><span>
</span><span style="color:#282828;">Created tunnel lxd-adguard with id xxx-yyy-zzz-aaa-bbb
</span></code></pre>
<p>Catat baik-baik itu tunnel id dan tunnel credential-nya</p>
<h2 id="kelima-bikin-config-untuk-cloudflared">Kelima, bikin config untuk cloudflared</h2>
<p>Aku harus cek ip dari container adguard yang akan aku expose ke internet</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>┌─[sumar][tingpret][~/opt]
</span><span>└─▪ lxc list
</span><span>+---------------------+---------+----------------------+-----------------------------------------------+-----------+-----------+
</span><span>| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
</span><span>+---------------------+---------+----------------------+-----------------------------------------------+-----------+-----------+
</span><span>| adguard | RUNNING | 10.179.72.2 (eth0) | fd42:26d1:59e3:5a35:216:3eff:fe79:2cd9 (eth0) | CONTAINER | 0 |
</span><span>+---------------------+---------+----------------------+-----------------------------------------------+-----------+-----------+
</span></code></pre>
<p>IP container-nya adalah 10.179.72.2, port-nya kebetulan aku set ke 80 di dalam kontainer.</p>
<p>Lanjut aku bikin <code>/home/sumar/.cloudflared/config.yml</code></p>
<pre data-lang="yaml" style="background-color:#fcf0ca;color:#282828aa;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span style="font-weight:bold;color:#407959;">credentials-file</span><span>: </span><span style="color:#79740e;">/home/sumar/.cloudflared/xxx-yyy-zzz-aaa-bbb.json
</span><span style="font-weight:bold;color:#407959;">tunnel</span><span>: </span><span style="color:#79740e;">xxx-yyy-zzz-aaa-bbb
</span><span>
</span><span style="font-weight:bold;color:#407959;">ingress</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">hostname</span><span>: </span><span style="color:#79740e;">adguard.sumarsono.com
</span><span> </span><span style="font-weight:bold;color:#407959;">service</span><span>: </span><span style="color:#79740e;">http://10.179.72.2:80
</span><span> - </span><span style="font-weight:bold;color:#407959;">service</span><span>: </span><span style="color:#79740e;">http_status:404
</span></code></pre>
<ul>
<li>hostname: adguard.sumarsono.com merupakan subdomain untuk expose app</li>
<li>service: http://10.179.72.2:80 ini adalah target, service di lokal, dalam hal ini container</li>
<li>service: http_status:404 ini catch all</li>
</ul>
<h2 id="keenam-bikin-subdomain">Keenam, bikin subdomain</h2>
<p>Sesuai config, aku bikin subdomain adguard.sumarsono.com</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">┌─[sumar][tingpret][~/opt]
</span><span style="color:#282828;">└─▪ cloudflared tunnel route dns xxx-yyy-zzz-aaa-bbb adguard.sumarsono.com
</span></code></pre>
<h2 id="terakhir-jalankan-cloudflared">Terakhir, jalankan cloudflared</h2>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">┌─[sumar][tingpret][~/opt]
</span><span style="color:#282828;">└─▪ cloudflared tunnel --config /home/sumar/.cloudflared/config.yml run
</span></code></pre>
<p>Sekarang kalau aku akses https://adguard.sumarsono.com akan tampil halaman login adguard yang aku host di lxd container di laptopku.</p>
<p>Referensi:</p>
<ul>
<li><a href="https://blog.cloudflare.com/argo-tunnels-that-live-forever/">Argo Tunnels that live forever</a></li>
<li><a href="https://blog.cloudflare.com/tunnel-for-everyone/">A Boring Announcement: Free Tunnels for Everyone</a></li>
<li><a href="https://developers.cloudflare.com/cloudflare-one/connections/connect-apps">Connect applications</a></li>
</ul>
Setup Haproxy Dan Keepalived Di Debian 10
2021-03-31T15:58:51+07:00
2021-03-31T15:58:51+07:00
Unknown
https://www.sumarsono.com/setup-haproxy-dan-keepalived-di-debian-10/
<p>Untuk membuat HA HAProxy on premise, aku pakai Keepalived. Keepalived disini berperan sebagai penjaga Floating IP, untuk fail over ketika master0 mati maka keepalived akan assign floating ip ke master1 atau master2.</p>
<h2 id="lab-setup">Lab Setup</h2>
<ul>
<li>Pakai 3 node, masing-masing kuberi nama master0, master1, dan master2</li>
<li>Network Subnet: 10.179.72.0/24</li>
<li>Floating IP: <strong>10.179.72.200/24</strong></li>
<li>master0 IP Address: 10.179.72.245/24</li>
<li>master1 IP Address: 10.179.72.211/24</li>
<li>master2 IP Address: 10.179.72.47/24</li>
<li>Operating System: Debian 10 (Buster)</li>
<li>KeepAlived version: v2.0.10 (11/12,2018)</li>
<li>Haproxy version: 2.2.8-1~bpo10+1 2021/01/14</li>
</ul>
<blockquote>
<p>Note: Disini aku memakai keepalived dengan unicast, krn environment engga mendukung untuk multicast.</p>
</blockquote>
<h2 id="install-keepalived-dan-haproxy-di-semua-node-master0-master1-dan-master2">Install keepalived dan haproxy di semua node (master0, master1, dan master2)</h2>
<p>Aku perlu menambahkan repo haproxy karena mau pakai versi 2.2 LTS yang belum masuk ke repo debian buster:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">root@master0:~# echo deb http://deb.debian.org/debian buster-backports main </span><span style="color:#b23c15;">></span><span style="color:#282828;"> /etc/apt/sources.list.d/backports.list
</span></code></pre>
<p>Kemudian update list package:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">root@master0:~# apt update
</span></code></pre>
<p>Lanjut install yang aku butuhkan:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">root@master0:~# apt install curl keepalived haproxy=2.2.</span><span style="color:#79740e;">\*</span><span style="color:#282828;"> -t buster-backports
</span></code></pre>
<p>Kemudian aku perlu setup beberapa parameter kernel yang dibutuhkan oleh keepalived dan haproxy untuk bind floating ip/virtual ip.</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">root@master0:~# vi /etc/sysctl.d/999-keepalived-haproxy.conf
</span><span>
</span><span style="color:#282828;">net.ipv4.ip_forward</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">1
</span><span style="color:#282828;">net.ipv4.ip_nonlocal_bind</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">1
</span></code></pre>
<p>Aku apply parameter kernel tersebut tanpa reboot:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">root@master0:~# sysctl -p
</span></code></pre>
<p>Ulangi semua langkah di node master1 dan master2</p>
<h2 id="konfigurasi-keepalived-dan-haproxy-di-master0">Konfigurasi keepalived dan haproxy di master0</h2>
<p>Node Master0 akan aku jadikan master untuk keepalived, sedangkan master1 dan master2 akan aku jadikan backup untuk keepalived. Perlu di juga perhatikan bagian unicast_src_ip dan unicast_peer.</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">root@master0:~# vi /etc/keepalived/keepalived.conf
</span><span>
</span><span style="font-style:italic;color:#928374;"># konfigurasi yang aku pakai:
</span><span style="color:#282828;">global_defs {
</span><span style="color:#282828;"> router_id LVS_DEVEL
</span><span style="color:#282828;">}
</span><span style="color:#282828;">vrrp_script check_apiserver {
</span><span style="color:#282828;"> script </span><span style="color:#79740e;">"/usr/bin/killall -0 haproxy"
</span><span style="color:#282828;"> interval 3
</span><span style="color:#282828;"> weight -2
</span><span style="color:#282828;"> fall 10
</span><span style="color:#282828;"> rise 2
</span><span style="color:#282828;">}
</span><span>
</span><span style="color:#282828;">vrrp_instance VI_1 {
</span><span style="color:#282828;"> state MASTER
</span><span style="color:#282828;"> interface eth0
</span><span style="color:#282828;"> virtual_router_id 51
</span><span style="color:#282828;"> priority 101
</span><span style="color:#282828;"> unicast_src_ip 10.179.72.245
</span><span style="color:#282828;"> unicast_peer {
</span><span style="color:#282828;"> 10.179.72.211
</span><span style="color:#282828;"> 10.179.72.47
</span><span style="color:#282828;"> }
</span><span style="color:#282828;">
</span><span style="color:#282828;"> authentication {
</span><span style="color:#282828;"> auth_type PASS
</span><span style="color:#282828;"> auth_pass 42
</span><span style="color:#282828;"> }
</span><span style="color:#282828;"> virtual_ipaddress {
</span><span style="color:#282828;"> 10.179.72.200
</span><span style="color:#282828;"> }
</span><span style="color:#282828;"> track_script {
</span><span style="color:#282828;"> check_apiserver
</span><span style="color:#282828;"> }
</span><span style="color:#282828;">}
</span><span>
</span></code></pre>
<h2 id="konfigurasi-keepalived-dan-haproxy-di-master1">Konfigurasi keepalived dan haproxy di master1</h2>
<p>Keepalived di master1 aku konfig sebagai backup dengan priority lebih rendah dari master0. Perlu diperhatikan bagian unicast_src_ip dan unicast_peer</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">root@master1:~# vi /etc/keepalived/keepalived.conf
</span><span>
</span><span style="font-style:italic;color:#928374;"># konfigurasi yang aku pakai:
</span><span style="color:#282828;">global_defs {
</span><span style="color:#282828;"> router_id LVS_DEVEL
</span><span style="color:#282828;">}
</span><span style="color:#282828;">vrrp_script check_apiserver {
</span><span style="color:#282828;"> script </span><span style="color:#79740e;">"/usr/bin/killall -0 haproxy"
</span><span style="color:#282828;"> interval 3
</span><span style="color:#282828;"> weight -2
</span><span style="color:#282828;"> fall 10
</span><span style="color:#282828;"> rise 2
</span><span style="color:#282828;">}
</span><span>
</span><span style="color:#282828;">vrrp_instance VI_1 {
</span><span style="color:#282828;"> state BACKUP
</span><span style="color:#282828;"> interface eth0
</span><span style="color:#282828;"> virtual_router_id 51
</span><span style="color:#282828;"> priority 100
</span><span style="color:#282828;"> unicast_src_ip 10.179.72.211
</span><span style="color:#282828;">
</span><span style="color:#282828;"> unicast_peer {
</span><span style="color:#282828;"> 10.179.72.245
</span><span style="color:#282828;"> 10.179.72.47
</span><span style="color:#282828;"> }
</span><span style="color:#282828;">
</span><span style="color:#282828;"> authentication {
</span><span style="color:#282828;"> auth_type PASS
</span><span style="color:#282828;"> auth_pass 42
</span><span style="color:#282828;"> }
</span><span style="color:#282828;"> virtual_ipaddress {
</span><span style="color:#282828;"> 10.179.72.200
</span><span style="color:#282828;"> }
</span><span style="color:#282828;"> track_script {
</span><span style="color:#282828;"> check_apiserver
</span><span style="color:#282828;"> }
</span><span style="color:#282828;">}
</span><span>
</span></code></pre>
<h2 id="konfigurasi-keepalived-di-master2">Konfigurasi keepalived di master2</h2>
<p>Keepalived di master1 aku konfig sebagai backup dengan priority lebih rendah dari master0 dan master1. Perlu diperhatikan bagian unicast_src_ip dan unicast_peer.</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">root@master2:~# vi /etc/keepalived/keepalived.conf
</span><span>
</span><span style="font-style:italic;color:#928374;"># konfigurasi yang aku pakai:
</span><span style="color:#282828;">global_defs {
</span><span style="color:#282828;"> router_id LVS_DEVEL
</span><span style="color:#282828;">}
</span><span style="color:#282828;">vrrp_script check_apiserver {
</span><span style="color:#282828;"> script </span><span style="color:#79740e;">"/usr/bin/killall -0 haproxy"
</span><span style="color:#282828;"> interval 3
</span><span style="color:#282828;"> weight -2
</span><span style="color:#282828;"> fall 10
</span><span style="color:#282828;"> rise 2
</span><span style="color:#282828;">}
</span><span>
</span><span style="color:#282828;">vrrp_instance VI_1 {
</span><span style="color:#282828;"> state BACKUP
</span><span style="color:#282828;"> interface eth0
</span><span style="color:#282828;"> virtual_router_id 51
</span><span style="color:#282828;"> priority 99
</span><span style="color:#282828;"> unicast_src_ip 10.179.72.47
</span><span style="color:#282828;">
</span><span style="color:#282828;"> unicast_peer {
</span><span style="color:#282828;"> 10.179.72.211
</span><span style="color:#282828;"> 10.179.72.245
</span><span style="color:#282828;"> }
</span><span style="color:#282828;">
</span><span style="color:#282828;"> authentication {
</span><span style="color:#282828;"> auth_type PASS
</span><span style="color:#282828;"> auth_pass 42
</span><span style="color:#282828;"> }
</span><span style="color:#282828;"> virtual_ipaddress {
</span><span style="color:#282828;"> 10.179.72.200
</span><span style="color:#282828;"> }
</span><span style="color:#282828;"> track_script {
</span><span style="color:#282828;"> check_apiserver
</span><span style="color:#282828;"> }
</span><span style="color:#282828;">}
</span></code></pre>
<p>Perbedaan dari konfigurasi keepalived MASTER dan BACKUP:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">[sumar@tingpret ~]$ diff master0-keepalived.conf master1-keepalived.conf
</span><span style="color:#282828;">13c13
</span><span style="color:#b23c15;"><</span><span> state </span><span style="color:#282828;">MASTER
</span><span style="color:#282828;">---
</span><span style="color:#b23c15;">></span><span> state </span><span style="color:#282828;">BACKUP
</span><span style="color:#282828;">16,17c16,17
</span><span style="color:#b23c15;"><</span><span> priority </span><span style="color:#282828;">101
</span><span style="color:#b23c15;"><</span><span> unicast_src_ip </span><span style="color:#282828;">10.179.72.245
</span><span style="color:#282828;">---
</span><span style="color:#b23c15;">></span><span> priority </span><span style="color:#282828;">100
</span><span style="color:#b23c15;">></span><span> unicast_src_ip </span><span style="color:#282828;">10.179.72.211
</span><span style="color:#282828;">20c20
</span><span style="color:#b23c15;">< </span><span style="color:#8f3f71;">10</span><span style="color:#282828;">.179.72.211
</span><span style="color:#282828;">---
</span><span style="color:#b23c15;">> </span><span style="color:#8f3f71;">10</span><span style="color:#282828;">.179.72.245
</span><span style="color:#282828;">[sumar@tingpret ~]$ diff master0-keepalived.conf master2-keepalived.conf
</span><span style="color:#282828;">13c13
</span><span style="color:#b23c15;"><</span><span> state </span><span style="color:#282828;">MASTER
</span><span style="color:#282828;">---
</span><span style="color:#b23c15;">></span><span> state </span><span style="color:#282828;">BACKUP
</span><span style="color:#282828;">16,17c16,17
</span><span style="color:#b23c15;"><</span><span> priority </span><span style="color:#282828;">101
</span><span style="color:#b23c15;"><</span><span> unicast_src_ip </span><span style="color:#282828;">10.179.72.245
</span><span style="color:#282828;">---
</span><span style="color:#b23c15;">></span><span> priority </span><span style="color:#282828;">99
</span><span style="color:#b23c15;">></span><span> unicast_src_ip </span><span style="color:#282828;">10.179.72.47
</span><span style="color:#282828;">21c21
</span><span style="color:#b23c15;">< </span><span style="color:#8f3f71;">10</span><span style="color:#282828;">.179.72.47
</span><span style="color:#282828;">---
</span><span style="color:#b23c15;">> </span><span style="color:#8f3f71;">10</span><span style="color:#282828;">.179.72.245
</span><span style="color:#282828;">[sumar@tingpret ~]$ diff master1-keepalived.conf master2-keepalived.conf
</span><span style="color:#282828;">16,17c16,17
</span><span style="color:#b23c15;"><</span><span> priority </span><span style="color:#282828;">100
</span><span style="color:#b23c15;"><</span><span> unicast_src_ip </span><span style="color:#282828;">10.179.72.211
</span><span style="color:#282828;">---
</span><span style="color:#b23c15;">></span><span> priority </span><span style="color:#282828;">99
</span><span style="color:#b23c15;">></span><span> unicast_src_ip </span><span style="color:#282828;">10.179.72.47
</span><span style="color:#282828;">19a20
</span><span style="color:#b23c15;">> </span><span style="color:#8f3f71;">10</span><span style="color:#282828;">.179.72.211
</span><span style="color:#282828;">21d21
</span><span style="color:#b23c15;">< </span><span style="color:#8f3f71;">10</span><span style="color:#282828;">.179.72.47
</span></code></pre>
<p>Yang membedakan adalah <code>state</code> , <code>priority</code> , <code>unicast_src_ip</code> , <code>unicast_peer</code> </p>
<h2 id="konfigurasi-haproxy-di-semua-node-master0-master1-dan-master2">Konfigurasi haproxy di semua node (master0, master1, dan master2)</h2>
<p>Konfigurasi untuk haproxy adalah sama untuk semua node.</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">root@master0:~# vi /etc/haproxy/haproxy.cfg
</span><span>
</span><span style="font-style:italic;color:#928374;"># configurasi yang aku pakai:
</span><span style="color:#282828;">global
</span><span> </span><span style="color:#282828;">log /dev/log local0
</span><span> </span><span style="color:#282828;">log /dev/log local1 notice
</span><span> </span><span style="color:#282828;">chroot /var/lib/haproxy
</span><span> </span><span style="color:#282828;">stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
</span><span> </span><span style="color:#282828;">stats timeout 30s
</span><span> </span><span style="color:#282828;">user haproxy
</span><span> </span><span style="color:#282828;">group haproxy
</span><span> </span><span style="color:#282828;">daemon
</span><span>
</span><span> </span><span style="font-style:italic;color:#928374;"># Default SSL material locations
</span><span> </span><span style="color:#282828;">ca-base /etc/ssl/certs
</span><span> </span><span style="color:#282828;">crt-base /etc/ssl/private
</span><span>
</span><span> </span><span style="font-style:italic;color:#928374;"># See: https://ssl-config.mozilla.org/#server=haproxy&server-version=2.0.3&config=intermediate
</span><span> </span><span style="color:#282828;">ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
</span><span> </span><span style="color:#282828;">ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
</span><span> </span><span style="color:#282828;">ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
</span><span>
</span><span style="color:#282828;">defaults
</span><span> </span><span style="color:#282828;">log global
</span><span> </span><span style="color:#282828;">mode http
</span><span> </span><span style="color:#282828;">option httplog
</span><span> </span><span style="color:#282828;">option dontlognull
</span><span> </span><span style="color:#282828;">timeout connect 5000
</span><span> </span><span style="color:#282828;">timeout client 50000
</span><span> </span><span style="color:#282828;">timeout server 50000
</span><span> </span><span style="color:#282828;">errorfile 400 /etc/haproxy/errors/400.http
</span><span> </span><span style="color:#282828;">errorfile 403 /etc/haproxy/errors/403.http
</span><span> </span><span style="color:#282828;">errorfile 408 /etc/haproxy/errors/408.http
</span><span> </span><span style="color:#282828;">errorfile 500 /etc/haproxy/errors/500.http
</span><span> </span><span style="color:#282828;">errorfile 502 /etc/haproxy/errors/502.http
</span><span> </span><span style="color:#282828;">errorfile 503 /etc/haproxy/errors/503.http
</span><span> </span><span style="color:#282828;">errorfile 504 /etc/haproxy/errors/504.http
</span><span>
</span><span style="font-style:italic;color:#928374;"># apiserver frontend, pakai ip floating
</span><span style="color:#282828;">frontend apiserver
</span><span> </span><span style="color:#b57614;">bind</span><span style="color:#282828;"> 10.179.72.200:8080
</span><span> </span><span style="color:#282828;">mode tcp
</span><span> </span><span style="color:#282828;">option tcplog
</span><span> </span><span style="color:#282828;">default_backend apiserver
</span><span>
</span><span style="font-style:italic;color:#928374;"># round robin balancing apiserver
</span><span style="color:#282828;">backend apiserver
</span><span> </span><span style="color:#282828;">option httpchk GET /healthprobe
</span><span> </span><span style="color:#282828;">http-check expect status 200
</span><span> </span><span style="color:#282828;">mode tcp
</span><span> </span><span style="color:#282828;">balance roundrobin
</span><span> </span><span style="color:#282828;">server apiku1 10.179.72.2:80 check
</span><span> </span><span style="color:#282828;">server apiku2 10.179.72.3:80 check
</span><span> </span><span style="color:#282828;">server apiku3 10.179.72.4:80 check
</span></code></pre>
<h2 id="enable-keepalived-dan-haproxy-di-semua-node-master0-master1-dan-master2">Enable keepalived dan haproxy di semua node (master0, master1, dan master2)</h2>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">root@master0:~# systemctl enable keepalived haproxy
</span><span style="color:#282828;">root@master0:~# systemctl restart keepalived haproxy
</span><span style="color:#282828;">root@master0:~# systemctl status keepalived haproxy
</span></code></pre>
<p>Ulangi untuk master1 dan master2.</p>
<h2 id="pengujian">Pengujian</h2>
<p>Kondisi setelah semua jalan, terlihat bahwa floating ip (10.179.72.200) ada di master0:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">+-------------+---------+----------------------+
</span><span style="color:#b23c15;">| </span><span style="color:#282828;">master0 </span><span style="color:#b23c15;">| </span><span style="color:#282828;">RUNNING </span><span style="color:#b23c15;">| </span><span style="color:#282828;">10.179.72.245 (eth0</span><span>) </span><span style="color:#b23c15;">|
</span><span style="color:#b23c15;">| | | </span><span style="color:#282828;">10.179.72.200 (eth0</span><span>) </span><span style="color:#b23c15;">|
</span><span style="color:#282828;">+-------------+---------+----------------------+
</span><span style="color:#b23c15;">| </span><span style="color:#282828;">master1 </span><span style="color:#b23c15;">| </span><span style="color:#282828;">RUNNING </span><span style="color:#b23c15;">| </span><span style="color:#282828;">10.179.72.211 (eth0</span><span>) </span><span style="color:#b23c15;">|
</span><span style="color:#282828;">+-------------+---------+----------------------+
</span><span style="color:#b23c15;">| </span><span style="color:#282828;">master2 </span><span style="color:#b23c15;">| </span><span style="color:#282828;">RUNNING </span><span style="color:#b23c15;">| </span><span style="color:#282828;">10.179.72.47 (eth0</span><span>) </span><span style="color:#b23c15;">|
</span><span style="color:#282828;">+-------------+---------+----------------------+
</span></code></pre>
<p>Aku coba curl ke floating ip tersebut + port yang aku konfig di HAProxy:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">[sumar@tingpret ~]$ curl -IL 10.179.72.200:8080
</span><span style="color:#282828;">HTTP/1.1 200 OK
</span><span style="color:#282828;">...
</span><span style="color:#282828;">Vary: Accept-Encoding
</span><span style="color:#282828;">Date: Wed, 31 Mar 2021 08:17:07 GMT
</span></code></pre>
<p>Good, request diteruskan ke apiserver di belakang haproxy.</p>
<p>Kemudian, coba matikan koneksi master0, atau shutdown nodenya juga bisa.</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">+-------------+---------+----------------------+
</span><span style="color:#b23c15;">| </span><span style="color:#282828;">master0 </span><span style="color:#b23c15;">| </span><span style="color:#282828;">STOPPED </span><span style="color:#b23c15;">| |
</span><span style="color:#282828;">+-------------+---------+----------------------+
</span><span style="color:#b23c15;">| </span><span style="color:#282828;">master1 </span><span style="color:#b23c15;">| </span><span style="color:#282828;">RUNNING </span><span style="color:#b23c15;">| </span><span style="color:#282828;">10.179.72.211 (eth0</span><span>) </span><span style="color:#b23c15;">|
</span><span style="color:#b23c15;">| | | </span><span style="color:#282828;">10.179.72.200 (eth0</span><span>) </span><span style="color:#b23c15;">|
</span><span style="color:#282828;">+-------------+---------+----------------------+
</span><span style="color:#b23c15;">| </span><span style="color:#282828;">master2 </span><span style="color:#b23c15;">| </span><span style="color:#282828;">RUNNING </span><span style="color:#b23c15;">| </span><span style="color:#282828;">10.179.72.47 (eth0</span><span>) </span><span style="color:#b23c15;">|
</span><span style="color:#282828;">+-------------+---------+----------------------+
</span></code></pre>
<p>Terlihat floating ip di pindahkan ke node master1. Lalu aku coba lagi curl:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">[sumar@tingpret ~]$ curl -IL 10.179.72.200:8080
</span><span style="color:#282828;">HTTP/1.1 200 OK
</span><span style="color:#282828;">...
</span><span style="color:#282828;">Vary: Accept-Encoding
</span><span style="color:#282828;">Date: Wed, 31 Mar 2021 08:20:17 GMT
</span></code></pre>
<p>Hasilnya good, request tetap diteruskan ke apiserver di belakang haproxy.</p>
<p>Sampai disini sudah selesai, semoga bermanfaat.</p>
<p>Cool~</p>
Haproxy Route Acme-tls/1
2021-03-15T15:54:53+07:00
2021-03-15T15:54:53+07:00
Unknown
https://www.sumarsono.com/haproxy-route-acme-tls-1/
<p>HAProxy v2.2 punya <code>req_ssl.alpn</code>. Deskripsinya aku kutip dari <a href="https://cbonte.github.io/haproxy-dconv/2.2/configuration.html">dokumentasi</a>:</p>
<blockquote>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>Returns a string containing the values of the Application-Layer Protocol
</span><span>Negotiation (ALPN) TLS extension (RFC7301), sent by the client within the SSL
</span><span>ClientHello message. Note that this only applies to raw contents found in the
</span><span>request buffer and not to the contents deciphered via an SSL data layer, so
</span><span>this will not work with "bind" lines having the "ssl" option. This is useful
</span><span>in ACL to make a routing decision based upon the ALPN preferences of a TLS
</span><span>client, like in the example below. See also "ssl_fc_alpn".
</span></code></pre>
</blockquote>
<p>Fitur tersebut sangat berguna ketika aku mau route validasi Let's Encrypt pakai Challenge <a href="https://letsencrypt.org/docs/challenge-types/#tls-alpn-01">TLS-ALPN-01</a> ke endpoint tertentu.</p>
<p>Singkatnya, seperti ini caraku routing protokol acme-tls/1 dari Let's encrypt</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>frontend tcp_443
</span><span> bind *:443
</span><span> mode tcp
</span><span> option tcplog
</span><span>
</span><span> tcp-request inspect-delay 5s
</span><span> tcp-request content capture req.ssl_sni len 25
</span><span> tcp-request content accept if { req_ssl_hello_type 1 }
</span><span>
</span><span> #
</span><span> # route to traefik if req ssl_alpn is acme-tls/1
</span><span> #
</span><span> use_backend traefikv1_acme if { req.ssl_alpn acme-tls/1 }
</span></code></pre>
<p>Penutup, aku tegaskan lagi catatan dari dokumentasi HAProxy: Note that <strong>this only applies to raw contents</strong> found in the request buffer and not to the contents deciphered via an SSL data layer, so this <strong>will not work</strong> <strong>with "bind" lines having the "ssl" option</strong>.</p>
HAproxy Dynamic Responses
2021-02-10T22:17:54+07:00
2021-02-10T22:17:54+07:00
Unknown
https://www.sumarsono.com/haproxy-dynamic-responses/
<p>Return custom response terhadap request tertentu, ketika pakai Nginx aku sering banget pakai ini. Seringnya aku pakai untuk cek "detak jantung" si nginx, dan <em>stateless</em> acme challenges. Contoh config-nya seperti ini</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>http {
</span><span>...
</span><span> server {
</span><span> ...
</span><span> location ~ ^/\.ping$ {
</span><span> default_type text/plain;
</span><span> return 200 "Pong!!!;
</span><span> }
</span><span> ...
</span><span> }
</span><span>}
</span></code></pre>
<p>Nah, di HAproxy juga ada fitur serupa, sayangnya baru ada sejak haproxy v2.2. Di Haproxy kita bisa pakai direktif <a href="https://cbonte.github.io/haproxy-dconv/2.2/configuration.html#http-request%20return">http-request return</a> . Dengan fitur itu maka aku bisa return response tanpa harus menyentuh backend, cukup di frontend aja, Contohnya begini:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>...
</span><span>frontend web
</span><span> bind :80
</span><span> bind :443 ssl crt /etc/haproxy/ssl/
</span><span> ...
</span><span> http-request return status 200 content-type "text/plain" string "Pong!!!" if { path_beg /ping }
</span><span> ...
</span><span> default_backend backend-web
</span><span>
</span></code></pre>
<p>Ketika di <code>cUrl</code></p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">[sumar@tingpret ~]$ curl -iL domainku.tld/ping
</span><span style="color:#282828;">HTTP/1.1 200 OK
</span><span style="color:#282828;">content-length: 7
</span><span style="color:#282828;">content-type: text/plain
</span><span>
</span><span style="color:#282828;">pong!!!
</span><span style="color:#282828;">[sumar@tingpret ~]$
</span><span>
</span></code></pre>
Melindungi Debian 10 Server Pakai Sshguard Dan Firewalld
2021-01-28T16:23:53+07:00
2021-01-28T16:23:53+07:00
Unknown
https://www.sumarsono.com/melindungi-debian-10-server-pakai-sshguard-dan-firewalld/
<p>Salah satu kewajiban dalam ngurus server adalah mengamankan jalur masuk ke server, yakni SSH. Salah satu cara untuk mengamankan akses SSH adalah dengan memakai sshguard. SSH guard berkeja dengan cara melakukan monitor terhadap log SSH dan melakukan tindakan pemblokiran terhadap IP yang berkali-kali gagal auth dengan memanfaatkan firewall yang ada pada system misalnya iptables, nftables, atau interface lebih tinggi yakni firewalld atau ufw.</p>
<blockquote>
<p><strong>sshguard</strong> is an intrusion prevention system that parses server logs, determines malicious activity, and uses the system firewall to block the IP addresses of malicious connections. sshguard is written in C so it does not tax an interpreter. -- <a href="https://wiki.gentoo.org/wiki/Sshguard">wiki gentoo</a></p>
<p><strong>sshguard</strong> protects hosts from brute-force attacks against SSH and other services. It aggregates system logs and blocks repeat offenders using one of several firewall backends, including <code>iptables</code>, <code>ipfw</code>, and <code>pf</code>. -- <a href="https://www.sshguard.net/">sshguard.net</a></p>
</blockquote>
<p>Aku secara pribadi lebih suka plain iptables, lebih mudah untuk custom rule aneh-aneh. Namun, semenjak debian 10 beralih ke nftables, aku lari ke firewalld. Sebab, aku belum begitu memahami nftables. Firewalld versi terakhir sudah mendukung nftables, makanya aku pakai firewalld aja.</p>
<blockquote>
<p><strong>Firewalld</strong> provides a dynamically managed firewall with support for network/firewall zones that define the trust level of network connections or interfaces. It has support for IPv4, IPv6 firewall settings, ethernet bridges and IP sets. There is a separation of runtime and permanent configuration options. It also provides an interface for services or applications to add firewall rules directly. -- <a href="https://firewalld.org/">firewalld.org</a></p>
</blockquote>
<p>Oleh sebab aku pakai Debian 10 dan Firewalld, maka beginilah proses instalasi dan konfirgurasi sshguard</p>
<p>Pertama, tentu aku install paket sshguard</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">apt update
</span><span style="color:#282828;">apt install sshguard
</span></code></pre>
<p>Kedua, config sshguard supaya pakai backend firewalld</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">nano /etc/sshguard/sshguard.conf
</span><span>
</span><span style="font-style:italic;color:#928374;"># isinya setelah aku edit
</span><span style="font-style:italic;color:#928374;">#### REQUIRED CONFIGURATION ####
</span><span style="font-style:italic;color:#928374;"># Full path to backend executable (required, no default)
</span><span style="font-style:italic;color:#928374;"># aku pakai firewalld
</span><span style="color:#282828;">BACKEND</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">"/usr/lib/x86_64-linux-gnu/sshg-fw-firewalld"
</span><span>
</span><span style="font-style:italic;color:#928374;"># Shell command that provides logs on standard output. (optional, no default)
</span><span style="font-style:italic;color:#928374;"># Example 1: ssh and sendmail from systemd journal:
</span><span style="color:#282828;">LOGREADER</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">"LANG=C /bin/journalctl -afb -p info -n1 -o cat SYSLOG_FACILITY=4 SYSLOG_FACILITY=10"
</span><span>
</span><span style="font-style:italic;color:#928374;">#### OPTIONS ####
</span><span style="font-style:italic;color:#928374;"># Block attackers when their cumulative attack score exceeds THRESHOLD.
</span><span style="font-style:italic;color:#928374;"># Most attacks have a score of 10. (optional, default 30)
</span><span style="color:#282828;">THRESHOLD</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">30
</span><span>
</span><span style="font-style:italic;color:#928374;"># Block attackers for initially BLOCK_TIME seconds after exceeding THRESHOLD.
</span><span style="font-style:italic;color:#928374;"># Subsequent blocks increase by a factor of 1.5. (optional, default 120)
</span><span style="font-style:italic;color:#928374;"># Blokir selama 24 hours (60480 seconds)
</span><span style="color:#282828;">BLOCK_TIME</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">60480
</span><span>
</span><span style="font-style:italic;color:#928374;"># Remember potential attackers for up to DETECTION_TIME seconds before
</span><span style="font-style:italic;color:#928374;"># resetting their score. (optional, default 1800)
</span><span style="font-style:italic;color:#928374;"># Track IP addresses selama 24 hours (60480 seconds)
</span><span style="color:#282828;">DETECTION_TIME</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">60480
</span><span>
</span><span style="font-style:italic;color:#928374;"># IP addresses listed in the WHITELIST_FILE are considered to be
</span><span style="font-style:italic;color:#928374;"># friendlies and will never be blocked.
</span><span style="color:#282828;">WHITELIST_FILE</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">/etc/sshguard/whitelist
</span></code></pre>
<p>Ketiga, restart dan enable service sshguard</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">systemctl restart sshguard
</span><span style="color:#282828;">systemctl enable sshguard
</span></code></pre>
<p>Kalau mau melihat sshguard beraksi, silakan pakai journalctl</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">root@wiki:/home/sumar# LANG=C /bin/journalctl -afb -p info -n1 -o cat SYSLOG_FACILITY=4 SYSLOG_FACILITY=10
</span></code></pre>
<p>Contoh outputnya dapat dilihat digambar</p>
<p><img src="https://telegra.ph/file/1dd32194959522a14f8fc.png" alt="SSHGuard in action" /></p>
<p>Dari gambar nampak:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">...
</span><span style="color:#282828;">Blocking </span><span style="color:#79740e;">"192.241.210.26/32"</span><span style="color:#282828;"> for 60480 secs (3 attacks in 1 secs, after 1 abuses over 1 secs.</span><span>)
</span><span style="color:#282828;">...
</span><span style="color:#282828;">Blocking </span><span style="color:#79740e;">"221.181.185.140/32"</span><span style="color:#282828;"> for 60480 secs (3 attacks in 1 secs, after 1 abuses over 1 secs.</span><span>)
</span></code></pre>
<p>Itu artinya sshguard sudah berjalan sebagaimana mestinya.</p>
<p>Untuk cek daftar IP Address yang terblokir gunakan perintah:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">root@wiki:/home/sumar# firewall-cmd --info-ipset</span><span style="color:#b23c15;">=</span><span style="color:#282828;">sshguard4
</span><span>
</span><span style="font-style:italic;color:#928374;"># outputnya
</span><span style="color:#282828;">sshguard4
</span><span> </span><span style="color:#282828;">type: hash:net
</span><span> </span><span style="color:#282828;">options: family=inet
</span><span> </span><span style="color:#282828;">entries: 192.241.210.26/32 221.181.185.140/32 221.131.165.124/32 221.181.185.223/32 139.59.144.132/32 81.161.63.254/32 62.221.121.185/32
</span><span>
</span></code></pre>
<p>Sekali lagi konteksnya aku pakai debian 10, nftables, dan firewald.</p>
<p>Cool~</p>
Inbucket - Self Hosted Disposable Email Server
2021-01-27T13:48:23+07:00
2021-01-27T13:48:23+07:00
Unknown
https://www.sumarsono.com/inbucket-self-hosted-disposable-email-server/
<h2 id="latar-belakang">Latar Belakang</h2>
<p>Jadi gini, aku pengen punya satu email server dengan kriteria:</p>
<ol>
<li>Inbound only, email server cuma bisa nerima tanpa bisa ngirim. Demi mencegah terjadinya open relay dan nyebarin spam.</li>
<li>Catch all, email server akan menerima semua email dengan alamat apapun yang ditujukan kepadanya tanpa harus aku bikin akun emailnya. </li>
<li>Web UI, email server didukung oleh web ui untuk melihat email-email yang masuk .</li>
<li>REST API, kalau bisa ada ini untuk integrasi ke mainan lain.</li>
<li>Instalasi sederhana, aku tidak mau overkill untuk hal semacam ini. Maunya yg sederhana, run single binary dan beres.</li>
</ol>
<p>Pernah dengar temp-mail? atau Mailinator? atau mailsac? nah kurang lebih fungsinya sama seperti itu. Nama hits-nya adalah "Disposable email", ada beberapa manfaat:</p>
<ol>
<li>Mendaftar layanan dengan email sembarangan, jadinya gk ngotorin inbox email pribadi/utama.</li>
<li>Melakukan testing aplikasi tanpa harus kirim email ke dunia luar, tetap private.</li>
</ol>
<p>Setelah menyelam, aku dapat dua kandidat:</p>
<ol>
<li>MailHog, Web and API based SMTP testing.</li>
<li>Inbucket, Disposable webmail server with built in SMTP, POP3, RESTful servers; no DB required.</li>
</ol>
<p>Setelah lihat-lihat, pilihan jatuh ke Inbucket dengan alasan development masih aktif.</p>
<h2 id="setup-inbucket-disposable-email-server-di-debian-10">Setup Inbucket Disposable email server di Debian 10</h2>
<p><strong>Pertama</strong>, aku generate config untuk inbucket dengan configurator yang mereka sediakan, silakan buka <a href="https://www.inbucket.org/configurator/">Inbucket Configurator</a></p>
<p>Hasil akhirnya adalah sebagai berikut, aku ambil yg versi systemd:</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_LOGLEVEL=error
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_MAILBOXNAMING=full
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_SMTP_ADDR=0.0.0.0:25
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_SMTP_DOMAIN=emx.sumarsono.com
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_SMTP_MAXRECIPIENTS=100
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_SMTP_MAXMESSAGEBYTES=10240000
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_SMTP_DEFAULTACCEPT=false
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_SMTP_ACCEPTDOMAINS=sumarsono.com,nalakawula.com
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_SMTP_DEFAULTSTORE=false
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_SMTP_STOREDOMAINS=sumarsono.com,nalakawula.com
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_SMTP_TIMEOUT=300s
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_POP3_ADDR=127.0.0.1:1100
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_POP3_DOMAIN=sumarsono.com
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_POP3_TIMEOUT=600s
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_WEB_ADDR=127.0.0.1:9000
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_WEB_UIDIR=/usr/local/share/inbucket/ui
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_WEB_GREETINGFILE=/etc/inbucket/greeting.html
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_WEB_TEMPLATECACHE=true
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_WEB_MAILBOXPROMPT=@sumarsono.com
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_WEB_COOKIEAUTHKEY=tKa8mGD7tqwCuYezdbE4chkQRxSotpCfs4ucB
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_WEB_MONITORVISIBLE=true
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_WEB_MONITORHISTORY=30
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_STORAGE_TYPE=file
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_STORAGE_PARAMS=path:/var/local/inbucket
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_STORAGE_RETENTIONPERIOD=720h
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_STORAGE_RETENTIONSLEEP=86400s
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_STORAGE_MAILBOXMSGCAP=100
</span></code></pre>
<p>Catatan:</p>
<ol>
<li>Aku gak butuh POP3, makanya bind ke 127.0.0.1</li>
<li>Email server akan menerima alamat apapun@sumarsono.com dan apapun@nalakawula.com</li>
<li>Email yang masuk akan aku keep 30 hari</li>
<li>Alamat web aku bind ke 127.0.0.1:9000 karena aku mau pakai reverse proxy untuk terminate SSL dan BasicAuth</li>
</ol>
<p><strong>Kedua</strong>, aku unduh paket inbucket dari <a href="https://github.com/inbucket/inbucket/releases">halaman rilis inbucket</a></p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">root@emx:~# wget https://github.com/inbucket/inbucket/releases/download/v3.0.0-rc1/inbucket_3.0.0-rc1_linux_amd64.deb
</span></code></pre>
<p><strong>Ketiga</strong>, tentu saja aku install</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">root@emx:~# dpkg -i inbucket_3.0.0-rc1_linux_amd64.deb
</span></code></pre>
<p><strong>Keempat</strong>, aku edit inbucket.service</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">root@emx:~# nano /lib/systemd/system/inbucket.service
</span><span>
</span><span style="font-style:italic;color:#928374;"># isinya sesuaikan dengan hasil generate di tahap 1
</span><span style="color:#282828;">[Unit]
</span><span style="color:#282828;">Description</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">Inbucket </span><span style="color:#282828;">Disposable Email Service
</span><span style="color:#282828;">After</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">network.target
</span><span>
</span><span style="color:#282828;">[Service]
</span><span style="color:#282828;">Type</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">simple
</span><span style="color:#282828;">User</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">daemon
</span><span style="color:#282828;">Group</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">daemon
</span><span style="color:#282828;">PermissionsStartOnly</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">true
</span><span>
</span><span style="font-style:italic;color:#928374;"># default conf
</span><span style="font-style:italic;color:#928374;">#Environment=INBUCKET_LOGLEVEL=warn
</span><span style="font-style:italic;color:#928374;">#Environment=INBUCKET_SMTP_ADDR=0.0.0.0:2500
</span><span style="font-style:italic;color:#928374;">#Environment=INBUCKET_POP3_ADDR=0.0.0.0:1100
</span><span style="font-style:italic;color:#928374;">#Environment=INBUCKET_WEB_ADDR=0.0.0.0:9000
</span><span style="font-style:italic;color:#928374;">#Environment=INBUCKET_WEB_UIDIR=/usr/local/share/inbucket/ui
</span><span style="font-style:italic;color:#928374;">#Environment=INBUCKET_WEB_GREETINGFILE=/etc/inbucket/greeting.html
</span><span style="font-style:italic;color:#928374;">#Environment=INBUCKET_STORAGE_TYPE=file
</span><span style="font-style:italic;color:#928374;">#Environment=INBUCKET_STORAGE_PARAMS=path:/var/local/inbucket
</span><span>
</span><span style="font-style:italic;color:#928374;"># Hasil generate tahap 1
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_LOGLEVEL=error
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_MAILBOXNAMING=full
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_SMTP_ADDR=0.0.0.0:25
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_SMTP_DOMAIN=sumarsono.com
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_SMTP_MAXRECIPIENTS=100
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_SMTP_MAXMESSAGEBYTES=10240000
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_SMTP_DEFAULTACCEPT=false
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_SMTP_ACCEPTDOMAINS=sumarsono.com,nalakawula.com
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_SMTP_DEFAULTSTORE=false
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_SMTP_STOREDOMAINS=sumarsono.com,nalakawula.com
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_SMTP_TIMEOUT=300s
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_POP3_ADDR=127.0.0.1:1100
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_POP3_DOMAIN=sumarsono.com
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_POP3_TIMEOUT=600s
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_WEB_ADDR=0.0.0.0:9000
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_WEB_UIDIR=/usr/local/share/inbucket/ui
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_WEB_GREETINGFILE=/etc/inbucket/greeting.html
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_WEB_TEMPLATECACHE=true
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_WEB_MAILBOXPROMPT=@sumarsono.com
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_WEB_COOKIEAUTHKEY=tKa8mGD7tqwCuYezdbE4chkQRxSotpCfs4ucB
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_WEB_MONITORVISIBLE=true
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_WEB_MONITORHISTORY=30
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_STORAGE_TYPE=file
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_STORAGE_PARAMS=path:/var/local/inbucket
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_STORAGE_RETENTIONPERIOD=720h
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_STORAGE_RETENTIONSLEEP=86400s
</span><span style="color:#282828;">Environment</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">INBUCKET_STORAGE_MAILBOXMSGCAP=100
</span><span>
</span><span style="font-style:italic;color:#928374;"># Uncomment line below to use low numbered ports
</span><span style="color:#282828;">ExecStartPre</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">/sbin/setcap 'cap_net_bind_service=+ep' </span><span style="color:#282828;">/usr/local/bin/inbucket
</span><span>
</span><span style="color:#282828;">ExecStartPre</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">/bin/mkdir </span><span style="color:#282828;">-p /var/local/inbucket
</span><span style="color:#282828;">ExecStartPre</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">/bin/chown </span><span style="color:#282828;">daemon:daemon /var/local/inbucket
</span><span>
</span><span style="color:#282828;">ExecStart</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">/usr/local/bin/inbucket
</span><span>
</span><span style="font-style:italic;color:#928374;"># Give SMTP connections time to drain
</span><span style="color:#282828;">TimeoutStopSec</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">20
</span><span style="color:#282828;">KillMode</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">mixed
</span><span>
</span><span style="color:#282828;">[Install]
</span><span style="color:#282828;">WantedBy</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">multi-user.target
</span></code></pre>
<p><strong>Kelima</strong>, enable dan start inbucket.service</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">root@emx:~# systemctl daemon-reload
</span><span style="color:#282828;">root@emx:~# systemctl enable --now inbucket.service
</span><span>
</span><span style="font-style:italic;color:#928374;"># verifikasi port-nya
</span><span style="color:#282828;">root@emx:~# ss -tulpn </span><span style="color:#b23c15;">| </span><span style="color:#282828;">grep inbucket
</span><span style="color:#282828;">tcp LISTEN 0 128 127.0.0.1:1100 0.0.0.0:</span><span style="color:#b23c15;">*</span><span style="color:#282828;"> users:((</span><span style="color:#79740e;">"inbucket"</span><span style="color:#282828;">,pid=13101,fd=8</span><span>))
</span><span style="color:#282828;">tcp LISTEN 0 128 0.0.0.0:25 0.0.0.0:</span><span style="color:#b23c15;">*</span><span style="color:#282828;"> users:((</span><span style="color:#79740e;">"inbucket"</span><span style="color:#282828;">,pid=13101,fd=6</span><span>))
</span><span style="color:#282828;">tcp LISTEN 0 128 127.0.0.1:9000 0.0.0.0:</span><span style="color:#b23c15;">*</span><span style="color:#282828;"> users:((</span><span style="color:#79740e;">"inbucket"</span><span style="color:#282828;">,pid=13101,fd=7</span><span>))
</span></code></pre>
<p><strong>Keenam</strong>, bikin dns record, aku cuma butuh value ini</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span># a record emx.sumarsono.com
</span><span>emx.sumarsono.com. 20 IN A 1xx.2xx.1xx.xx
</span><span>
</span><span># webui inbucket
</span><span>anuan.sumarsono.com. 300 IN CNAME emx.sumarsono.com.
</span><span>
</span><span># mx record sumarsono.com
</span><span>sumarsono.com. 300 IN MX 10 emx.sumarsono.com.
</span><span>
</span><span># mx record nalakawula.com
</span><span>nalakawula.com. 300 IN MX 10 emx.sumarsono.com.
</span></code></pre>
<p><strong>Ketujuh</strong>, bikin vhost (kebetulan pakai apache httpd) untuk reverse proxy webui inbucket dan websocketnya:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>VirtualHost *:80>
</span><span> ServerName anuan.sumarsono.com
</span><span>
</span><span> <Proxy *>
</span><span> AuthType Basic
</span><span> AuthName "Restricted Content"
</span><span> AuthUserFile /etc/apache2/.htpasswd-inbucket
</span><span> Require valid-user
</span><span> </Proxy>
</span><span>
</span><span> ProxyPreserveHost On
</span><span> ProxyPass / http://127.0.0.1:9000/
</span><span> ProxyPassReverse / http://127.0.0.1:9000/
</span><span>
</span><span> RewriteEngine on
</span><span>
</span><span> RewriteCond %{REQUEST_URI} ^/api/v1/monitor/messages [NC]
</span><span> RewriteCond %{HTTP:Upgrade} =websocket [NC]
</span><span> RewriteRule /(.*) ws://127.0.0.1:9000/$1 [P,L]
</span><span> RequestHeader unset Origin
</span><span></VirtualHost>
</span></code></pre>
<p><strong>Kedelapan</strong>, test kirim email ke sembarang@sumarsono.com dan sembarang@nalakawula.com, dalam hal ini aku coba ngirim dari gmail, emailnya masuk ke inbucket.</p>
<p><img src="https://telegra.ph/file/f5f4c01a182ad70575113.png" alt="Uji coba inbucket" /></p>
<p>dan jika aku klik salah satu email tersebut maka akan tampil:</p>
<p><img src="https://telegra.ph/file/ffa898ed429dbbf511146.png" alt="Uji coba inbucket 2" /></p>
<p>Selesai.</p>
<p>Cool~</p>
Firewalld Nftables Debian 10
2021-01-12T10:33:12+07:00
2021-01-12T10:33:12+07:00
Unknown
https://www.sumarsono.com/firewalld-nftables-debian-10/
<p>Debian 10 by default sudah pakai <a href="https://wiki.debian.org/nftables">nftables</a>. Menurut wiki, cara termudah untuk konfigurasi nftables menggunakan <a href="https://firewalld.org/">firewalld</a>, sayangnya di wiki tidak dijelaskan step by step secara rinci bagaimana cara pasang dan penggunaan firewalld dengan backend nftables. Ketika aku install firewalld dan mau pakai, eh error. Haha</p>
<p>Rupanya, firewalld perlu di config agar menggunakan backend nftables karena by default ia menggunakan iptables. Untuk set firewalld dan nftables sangat mudah, caranya buka berkas <code>/etc/firewalld/firewalld.conf</code> kemudian cari line berikut:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span># FirewallBackend
</span><span># Selects the firewall backend implementation.
</span><span># Choices are:
</span><span># - nftables (default)
</span><span># - iptables (iptables, ip6tables, ebtables and ipset)
</span><span>FirewallBackend=iptables
</span></code></pre>
<p>Ubahlah menjadi</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span># FirewallBackend
</span><span># Selects the firewall backend implementation.
</span><span># Choices are:
</span><span># - nftables (default)
</span><span># - iptables (iptables, ip6tables, ebtables and ipset)
</span><span>FirewallBackend=nftables
</span></code></pre>
<p>Selanjutnya restart <code>firewalld.service</code>, dengan begitu firewalld sudah berjalan dengan backend nftables.</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">firewall-cmd --zone</span><span style="color:#b23c15;">=</span><span style="color:#282828;">public --change-interface</span><span style="color:#b23c15;">=</span><span style="color:#282828;">eth0 --permanent
</span><span style="color:#282828;">firewall-cmd --zone</span><span style="color:#b23c15;">=</span><span style="color:#282828;">public --add-service</span><span style="color:#b23c15;">=</span><span style="color:#282828;">http --permanent
</span><span style="color:#282828;">firewall-cmd --zone</span><span style="color:#b23c15;">=</span><span style="color:#282828;">public --add-service</span><span style="color:#b23c15;">=</span><span style="color:#282828;">https --permanent
</span><span style="color:#282828;">firewall-cmd --zone</span><span style="color:#b23c15;">=</span><span style="color:#282828;">public --add-service</span><span style="color:#b23c15;">=</span><span style="color:#282828;">ssh --permanent
</span><span style="color:#282828;">firewall-cmd --reload
</span></code></pre>
<p>Begitulah cara setting firewalld di Debian 10 yang sudah memakai nftables.</p>
Coredns Dns Over TLS DoT
2021-01-05T20:13:59+07:00
2021-01-05T20:13:59+07:00
Unknown
https://www.sumarsono.com/coredns-dns-over-tls-dot/
<p>CoreDNS bisa forward query ke DNS over TLS (DoT) server, keren ya. Berikut ini contoh Corefile untuk CoreDNS supaya forward query ke DNS over TLS</p>
<p><strong>Corefile Google DNS over TLS</strong></p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>.:53 {
</span><span> any
</span><span> errors
</span><span> log
</span><span>
</span><span> forward . tls://8.8.8.8 tls://8.8.4.4 {
</span><span> tls_servername dns.google
</span><span> health_check 60s
</span><span> }
</span><span>}
</span></code></pre>
<p><strong>Corefile Cloudflare DNS over TLS</strong></p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>.:53 {
</span><span> any
</span><span> errors
</span><span> log
</span><span>
</span><span> forward . tls://1.1.1.1 tls://1.0.0.1 {
</span><span> tls_servername cloudflare-dns.com
</span><span> health_check 60s
</span><span> }
</span><span>}
</span></code></pre>
Pihole Docker Dan Doh Pihole Docker
2021-01-05T09:25:47+07:00
2021-01-05T09:25:47+07:00
Unknown
https://www.sumarsono.com/pihole-docker-dan-doh-pihole-docker/
<h2 id="pihole-docker">Pihole Docker</h2>
<p>Pihole Docker menggunakan docker-compose, dari developer pihole sudah menyediakan template yaml-nya. Untuk install pihole pakai docker caranya cukup mudah, syaratnya sudah install docker dan docker-compose.</p>
<p>Silakan gunakan <code>docker-compose.yaml</code> berikut ini (ini copas dari <a href="https://github.com/pi-hole/docker-pi-hole">pihole docker</a>):</p>
<pre data-lang="yaml" style="background-color:#fcf0ca;color:#282828aa;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span style="font-weight:bold;color:#407959;">version</span><span>: </span><span style="color:#79740e;">"3"
</span><span>
</span><span style="font-style:italic;color:#928374;"># More info at https://github.com/pi-hole/docker-pi-hole/ and https://docs.pi-hole.net/
</span><span style="font-weight:bold;color:#407959;">services</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">pihole</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">container_name</span><span>: </span><span style="color:#79740e;">pihole
</span><span> </span><span style="font-weight:bold;color:#407959;">image</span><span>: </span><span style="color:#79740e;">pihole/pihole:latest
</span><span> </span><span style="font-weight:bold;color:#407959;">ports</span><span>:
</span><span> - </span><span style="color:#79740e;">"53:53/tcp"
</span><span> - </span><span style="color:#79740e;">"53:53/udp"
</span><span> - </span><span style="color:#79740e;">"67:67/udp"
</span><span> - </span><span style="color:#79740e;">"10080:80/tcp"
</span><span> - </span><span style="color:#79740e;">"10443:443/tcp"
</span><span> </span><span style="font-weight:bold;color:#407959;">environment</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">TZ</span><span>: </span><span style="color:#79740e;">'Asia/Jakarta'
</span><span> </span><span style="font-weight:bold;color:#407959;">WEBPASSWORD</span><span>: </span><span style="color:#79740e;">'set pass web ui mu disini'
</span><span> </span><span style="font-style:italic;color:#928374;"># Volumes store your data between container upgrades
</span><span> </span><span style="font-weight:bold;color:#407959;">volumes</span><span>:
</span><span> - </span><span style="color:#79740e;">'./etc-pihole/:/etc/pihole/'
</span><span> - </span><span style="color:#79740e;">'./etc-dnsmasq.d/:/etc/dnsmasq.d/'
</span><span> </span><span style="font-style:italic;color:#928374;"># Recommended but not required (DHCP needs NET_ADMIN)
</span><span> </span><span style="font-style:italic;color:#928374;"># https://github.com/pi-hole/docker-pi-hole#note-on-capabilities
</span><span> </span><span style="font-weight:bold;color:#407959;">cap_add</span><span>:
</span><span> - </span><span style="color:#79740e;">NET_ADMIN
</span><span> </span><span style="font-weight:bold;color:#407959;">restart</span><span>: </span><span style="color:#79740e;">unless-stopped
</span><span>
</span></code></pre>
<p>Aku hanya menyesuaikan port webui, timezone, dan password untuk webui.</p>
<p>Next, tinggal up aja</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">docker-compose up -d
</span></code></pre>
<p>Tes query dns pakai pihole</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">dig @127.0.0.1 sumarsono.com
</span><span>
</span><span>
</span><span style="color:#b23c15;">; <<>></span><span> DiG </span><span style="color:#282828;">9.11.5-P4-5.1+deb10u2-Debian </span><span style="color:#b23c15;"><<>></span><span style="color:#282828;"> @127.0.0.1 sumarsono.com
</span><span style="color:#b23c15;">; </span><span>(</span><span style="color:#282828;">1 server found</span><span>)
</span><span>;</span><span style="color:#b23c15;">; </span><span style="color:#282828;">global options: +cmd
</span><span>;</span><span style="color:#b23c15;">; </span><span style="color:#282828;">Got answer:
</span><span>;</span><span style="color:#b23c15;">; </span><span style="color:#282828;">-</span><span style="color:#b23c15;">>></span><span style="color:#282828;">HEADER</span><span style="color:#b23c15;"><<- </span><span style="color:#9d0006;">opcode</span><span style="color:#282828;">: QUERY, status: NOERROR, id: 58090
</span><span style="color:#282828;">;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
</span><span style="color:#282828;">
</span><span style="color:#282828;">;; OPT PSEUDOSECTION:
</span><span style="color:#282828;">; EDNS: version: 0, flags:; udp: 4096
</span><span style="color:#282828;">;; QUESTION SECTION:
</span><span style="color:#282828;">;sumarsono.com. IN A
</span><span style="color:#282828;">
</span><span style="color:#282828;">;; ANSWER SECTION:
</span><span style="color:#282828;">sumarsono.com. 20 IN A 54.179.122.191
</span><span style="color:#282828;">sumarsono.com. 20 IN A 13.250.205.9
</span><span style="color:#282828;">
</span><span style="color:#282828;">;; Query time: 74 msec
</span><span style="color:#282828;">;; SERVER: 127.0.0.1#53(127.0.0.1)
</span><span style="color:#282828;">;; WHEN: Tue Jan 05 09:28:15 WIB 2021
</span><span style="color:#282828;">;; MSG SIZE rcvd: 100
</span></code></pre>
<h2 id="enable-doh-pihole-docker">Enable DoH Pihole Docker</h2>
<p>Untuk menggunakan DoH Pihole, aku akan memakai <code>cloudflared</code></p>
<p>siapkan direktory dan config untuk cloudflared:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">mkdir /etc/cloudflared/
</span><span style="color:#282828;">nano /etc/cloudflared/config.yml
</span></code></pre>
<p>isi dari <code>/etc/cloudflared/config.yml</code>:</p>
<pre data-lang="yaml" style="background-color:#fcf0ca;color:#282828aa;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span style="font-weight:bold;color:#407959;">proxy-dns</span><span>: </span><span style="color:#8f3f71;">true
</span><span style="font-weight:bold;color:#407959;">proxy-dns-address</span><span>: </span><span style="color:#8f3f71;">0.0.0.0
</span><span style="font-weight:bold;color:#407959;">proxy-dns-port</span><span>: </span><span style="color:#8f3f71;">5053
</span><span style="font-weight:bold;color:#407959;">proxy-dns-upstream</span><span>:
</span><span> - </span><span style="color:#79740e;">https://1.1.1.1/dns-query
</span><span> - </span><span style="color:#79740e;">https://1.0.0.1/dns-query
</span><span> </span><span style="font-style:italic;color:#928374;">#Uncomment following if you want to also want to use IPv6 for external DOH lookups
</span><span> </span><span style="font-style:italic;color:#928374;">#- https://[2606:4700:4700::1111]/dns-query
</span><span> </span><span style="font-style:italic;color:#928374;">#- https://[2606:4700:4700::1001]/dns-query
</span></code></pre>
<p>Perhatikan bagian <code>proxy-dns-address</code> aku sengaja bind semua address supaya mudah dipakai oleh pihole docker. Kemudian bagian <code>proxy-dns-port</code> aku set ke 5053 supaya tidak bentrok dengan dns server pihole docker.</p>
<p>Lanjut install <code>cloudflared</code></p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">wget https://bin.equinox.io/c/VdrWdbjqyF/cloudflared-stable-linux-amd64.deb
</span><span style="color:#282828;">apt-get install ./cloudflared-stable-linux-amd64.deb
</span><span style="color:#282828;">cloudflared -v
</span></code></pre>
<p>Eksekusi cloudflared</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">cloudflared service install --legacy
</span><span style="color:#282828;">systemctl enable --now cloudflared
</span><span style="color:#282828;">systemctl status cloudflared
</span></code></pre>
<p>Tes query DNS pakai cloudflared</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>dig @127.0.0.1 -p 5053 sumarsono.com
</span><span>
</span><span>
</span><span>; <<>> DiG 9.11.5-P4-5.1+deb10u2-Debian <<>> @127.0.0.1 -p5053 sumarsono.com
</span><span>; (1 server found)
</span><span>;; global options: +cmd
</span><span>;; Got answer:
</span><span>;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 21764
</span><span>;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
</span><span>
</span><span>;; OPT PSEUDOSECTION:
</span><span>; EDNS: version: 0, flags:; udp: 4096
</span><span>;; QUESTION SECTION:
</span><span>;sumarsono.com. IN A
</span><span>
</span><span>;; ANSWER SECTION:
</span><span>sumarsono.com. 20 IN A 128.199.185.38
</span><span>sumarsono.com. 20 IN A 157.230.35.153
</span><span>
</span><span>;; Query time: 103 msec
</span><span>;; SERVER: 127.0.0.1#5053(127.0.0.1)
</span><span>;; WHEN: Tue Jan 05 09:28:53 WIB 2021
</span><span>;; MSG SIZE rcvd: 100
</span></code></pre>
<p>Selanjutnya ganti upstream dns pihole ke cloudflared supaya bisa pakai DoH, pertama aku harus dapetin ip address docker0</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">ip a show docker0
</span><span>
</span><span style="font-style:italic;color:#928374;"># outputnya
</span><span style="color:#282828;">4: docker0: </span><span style="color:#b23c15;"><</span><span style="color:#282828;">NO-CARRIER,BROADCAST,MULTICAST,UP</span><span style="color:#b23c15;">></span><span style="color:#282828;"> mtu 1500 qdisc noqueue state DOWN group default
</span><span> </span><span style="color:#282828;">link/ether 02:42:19:12:23:45 brd ff:ff:ff:ff:ff:ff
</span><span> </span><span style="color:#282828;">inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
</span><span> </span><span style="color:#282828;">valid_lft forever preferred_lft forever
</span></code></pre>
<p>IP address dari docker0 adalah 172.17.0.1, aku akan pakai IP ini sebagai upstream dns dari pihole, aku buka webui pihole, kalau aku kebetulan di http://192.168.1.254:10080/admin/. <strong>Login > Settings > DNS</strong></p>
<p><img src="https://telegra.ph/file/b651c7494731f6dcd1e28.png" alt="Setting Upstream DNS server PiHole" /></p>
<p>isikan 172.17.0.1#5053 </p>
<p>Terakhir, ganti DNS Server Router supaya pakai DNS dari PiHole supaya semua device yang terhubung mendapatkan manfaat dari PiHole yang tadi diinstall</p>
<p><img src="https://telegra.ph/file/e807b2db7512b45877302.png" alt="DNS Router" /></p>
<p>Selesai, itu tadi caraku install pihole docker dan enable DoH pihole docker. Sangat mudah.</p>
Freebsd Install sudo Dan Menambahkan User Ke sudoers
2021-01-02T21:00:32+07:00
2021-01-02T21:00:32+07:00
Unknown
https://www.sumarsono.com/freebsd-install-sudo-dan-menambahkan-user-ke-sudoers/
<p>Aku memakai freeBSD 12</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">sumar@miniserver:~ $ freebsd-version</span><span style="color:#b23c15;">; </span><span style="color:#282828;">uname -a
</span><span style="color:#282828;">12.2-RELEASE
</span><span style="color:#282828;">FreeBSD miniserver 12.2-RELEASE FreeBSD 12.2-RELEASE r366954 GENERIC amd64
</span><span style="color:#282828;">sumar@miniserver:~ $
</span></code></pre>
<p>Aku setup dua user yakni <code>root</code> dan <code>sumar</code>, Ketika aku jalankan <code>sudo</code> muncul error:</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">sumar@miniserver:~ $ sudo ifconfig
</span><span style="color:#282828;">-sh: sudo: not found
</span></code></pre>
<p>FreeBSD by default memang tidak memasang binari <code>sudo</code>, oleh sebab itu perintah tersebut error. Lantas bagaimana cara install sudo di freeBSD 12?. <code>sudo</code> di freebsd dapat diinstall melalui <a href="https://www.freebsd.org/doc/handbook/ports-using.html">ports collections</a>. Untuk memsang sudo aku login ke console menggunakan akun root, kemudian menjalankan perintah berikut:</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">root@miniserver:~ </span><span style="font-style:italic;color:#928374;"># cd /usr/ports/security/sudo/
</span><span style="color:#282828;">root@miniserver:~ </span><span style="font-style:italic;color:#928374;"># make install clean
</span></code></pre>
<p>Memasang paket dari <a href="https://www.freebsd.org/doc/handbook/ports-using.html">ports collections</a> akan memakan waktu yang tidak sedikit karena itu akan compile di mesin secara langsung. Semakin kentang spek mesin yang dipakai, semakin lama compile nya. Haha. Setelah selesai, binari sudo akan terpasang di <code>/usr/local/bin/sudo</code></p>
<p>Selanjutnya, aku memasukan user <code>sumar</code> ke group <code>wheel</code></p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">root@miniserver:~ </span><span style="font-style:italic;color:#928374;"># pw group mod wheel -m sumar
</span></code></pre>
<p>Selanjutnya, aku setting sudoers untuk group <code>wheel</code> tersebut</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">root@miniserver:~ </span><span style="font-style:italic;color:#928374;"># vi /usr/local/etc/sudoers.d/wheel-group
</span><span>
</span><span style="font-style:italic;color:#928374;"># isinya
</span><span style="color:#282828;">wheel ALL=(ALL</span><span>) </span><span style="color:#282828;">ALL
</span></code></pre>
<p>Terakhir, test apakah user <code>sumar</code> sudah bisa menjalankan perintah sudo:</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">[sumar@tingpret ~]$ ssh sumar@192.168.1.254
</span><span style="color:#282828;">Password for sumar@miniserver:
</span><span style="color:#282828;">Last login: Sat Jan 2 13:42:38 2021 from 192.168.1.31
</span><span style="color:#282828;">FreeBSD 12.2-RELEASE r366954 GENERIC
</span><span>
</span><span style="color:#282828;">Welcome to FreeBSD!
</span><span>
</span><span style="color:#282828;">sumar@miniserver:~ $ sudo ifconfig
</span><span style="color:#282828;">Password:
</span><span style="color:#282828;">re0: flags=</span><span style="color:#8f3f71;">8843</span><span style="color:#b23c15;"><</span><span style="color:#282828;">UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST</span><span style="color:#b23c15;">></span><span style="color:#282828;"> metric 0 mtu 1500
</span><span> </span><span style="color:#282828;">options</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">8209b</span><span style="color:#b23c15;"><</span><span>RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,WOL_MAGIC,LINKSTATE</span><span style="color:#b23c15;">>
</span><span> </span><span style="color:#282828;">ether 9c:8e:99:48:27:61
</span><span> </span><span style="color:#282828;">inet 192.168.1.254 netmask 0xffffff00 broadcast 192.168.1.255
</span><span> </span><span style="color:#282828;">media: Ethernet autoselect (100baseTX </span><span style="color:#b23c15;"><</span><span style="color:#282828;">full-duplex</span><span style="color:#b23c15;">></span><span>)
</span><span> </span><span style="color:#282828;">status: active
</span><span> </span><span style="color:#282828;">nd6 options=</span><span style="color:#8f3f71;">29</span><span style="color:#b23c15;"><</span><span style="color:#282828;">PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL</span><span style="color:#b23c15;">>
</span><span style="color:#282828;">lo0: flags=</span><span style="color:#8f3f71;">8049</span><span style="color:#b23c15;"><</span><span style="color:#282828;">UP,LOOPBACK,RUNNING,MULTICAST</span><span style="color:#b23c15;">></span><span style="color:#282828;"> metric 0 mtu 16384
</span><span> </span><span style="color:#282828;">options</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">680003</span><span style="color:#b23c15;"><</span><span>RXCSUM,TXCSUM,LINKSTATE,RXCSUM_IPV6,TXCSUM_IPV6</span><span style="color:#b23c15;">>
</span><span> </span><span style="color:#282828;">inet6 ::1 prefixlen 128
</span><span> </span><span style="color:#282828;">inet6 fe80::1%lo0 prefixlen 64 scopeid 0x2
</span><span> </span><span style="color:#282828;">inet 127.0.0.1 netmask 0xff000000
</span><span> </span><span style="color:#282828;">groups: lo
</span><span> </span><span style="color:#282828;">nd6 options=</span><span style="color:#8f3f71;">21</span><span style="color:#b23c15;"><</span><span style="color:#282828;">PERFORMNUD,AUTO_LINKLOCAL</span><span style="color:#b23c15;">>
</span><span style="color:#282828;">sumar@miniserver:~ $
</span></code></pre>
<p>Sukses.</p>
<p>Nah itu tadi caraku memasang sudo di freebsd dan menambahkan sudoers user di freebsd.</p>
Backup Subvolume Snapshot Btrfs Ke Disk Lain
2021-01-02T11:51:00+07:00
2021-01-02T11:51:00+07:00
Unknown
https://www.sumarsono.com/backup-subvolume-snapshot-btrfs-ke-disk-lain/
<p>Aku punya instalasi distro linux yang memakai BTRFS untuk file system-nya. Salah satu nilai jual BTRFS adalah snapshot, yap berkat CoW aku bisa bikin snapshot subvolume btrfs sebelum ngulik sesuatu dan jika <em>shit happen</em> maka aku bisa <em>restore</em> ke subvolume hasil snapshot. Dan kasus sekarang aku ingin backup snapshot ke disk lain untuk jaga-jaga. Susunan Disk yang sekarang:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">SSD Samsung:
</span><span style="color:#b23c15;">|</span><span style="color:#282828;">__EFI
</span><span style="color:#b23c15;">|</span><span style="color:#282828;">__SWAP
</span><span style="color:#b23c15;">|</span><span style="color:#282828;">__BTRFS /
</span><span> </span><span style="color:#b23c15;">|</span><span style="color:#282828;">__subvol @ mount sebagai /
</span><span> </span><span style="color:#b23c15;">|</span><span style="color:#282828;">__subvol @home mount sebagai /home
</span><span> </span><span style="color:#b23c15;">|</span><span style="color:#282828;">__subvol @cache mount sebagai /cache
</span></code></pre>
<p>Rencananya aku akan snapshot subvolume <code>@</code> dan subvolume <code>@home</code> kemudian hasil snapshotnya akan aku backup ke SSD MidasForce. SSD MidasForce sudah aku format sebagai BTRFS. SSD tempat backup akan aku mount ke <code>/run/media/sumar/MidasForce/</code></p>
<p>Aku akan memakai fitur-fitur btrfs:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="font-style:italic;color:#928374;"># btrfs subvolume snapshot
</span><span style="font-style:italic;color:#928374;"># btrfs send
</span><span style="font-style:italic;color:#928374;"># btrfs receive
</span></code></pre>
<p>Berikut ini adalah langkah-langkah backup snapshot subvolume btrfs ke disk lain:</p>
<ol>
<li>
<p>Bikin read only snapshot</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="font-style:italic;color:#928374;"># bikin direktori utk menampung snapshot
</span><span style="color:#282828;">sudo mkdir /.snapshots
</span><span>
</span><span style="font-style:italic;color:#928374;"># snapshot subvolume @home
</span><span style="color:#282828;">sudo btrfs subvolume snapshot -r /home /.snapshots/home.$(date +%Y-%m-%d)
</span><span>
</span><span style="font-style:italic;color:#928374;"># snapshot subvolume @
</span><span style="color:#282828;">sudo btrfs subvolume snapshot -r / /.snapshots/root.$(date +%Y-%m-%d)
</span><span>
</span><span style="font-style:italic;color:#928374;"># write ram cache to disk
</span><span style="color:#282828;">sudo sync
</span></code></pre>
</li>
<li>
<p>Kirim snapshot tersebut ke disk lain pakai <code>btrfs send</code> dan <code>btrfs receive</code></p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="font-style:italic;color:#928374;"># backup snapshot @home ke Disk lain
</span><span style="color:#282828;">sudo btrfs send /.snapshots/home.2021-01-02 </span><span style="color:#b23c15;">| </span><span style="color:#282828;">sudo btrfs receive /run/media/sumar/MidasForce/
</span><span>
</span><span style="font-style:italic;color:#928374;"># backup snapshot @ ke Disk lain
</span><span style="color:#282828;">sudo btrfs send /.snapshots/root.2021-01-02 </span><span style="color:#b23c15;">| </span><span style="color:#282828;">sudo btrfs receive /run/media/sumar/MidasForce/
</span></code></pre>
<p>Akan memakan waktu cukup lama karena backup pertama kali adalah full backup.</p>
</li>
<li>
<p>Incremental backup</p>
<p>Hari berikutnya buatlah snapshot, kemudian backup lagi pakai send receive</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="font-style:italic;color:#928374;"># incremental backup snapshot @home
</span><span style="color:#282828;">sudo btrfs send -p /.snapshots/home.2021-01-02 /.snapshots/home.2021-01-03 </span><span style="color:#b23c15;">| </span><span style="color:#282828;">sudo btrfs receive /run/media/sumar/MidasForce/
</span><span>
</span><span style="font-style:italic;color:#928374;"># incremental backup snapshot @
</span><span style="color:#282828;">sudo btrfs send -p /.snapshots/root.2021-01-02 /.snapshots/root.2021-01-03 </span><span style="color:#b23c15;">| </span><span style="color:#282828;">sudo btrfs receive /run/media/sumar/MidasForce/
</span></code></pre>
<p>Akan memakan waktu cukup singkat, karena incremental.</p>
</li>
</ol>
<p>Referensi:</p>
<ol>
<li><a href="https://btrfs.wiki.kernel.org/index.php/Incremental_Backup">BTRFS Wiki</a></li>
<li><a href="https://fedoramagazine.org/btrfs-snapshots-backup-incremental/">Fedora Magazine</a></li>
</ol>
Fix Fatal error: Allowed memory size of 1610612736 bytes exhausted (tried to allocate 4096 bytes)
2020-12-30T14:20:14+07:00
2020-12-30T14:20:14+07:00
Unknown
https://www.sumarsono.com/fix-composer-fatal-error-allowed-memory-size-of-1610612736-bytes-exhausted/
<p>Baru-baru ini aku diminta benerin web yang di host di suatu jasa web hosting. Setelah menelusuri log, web tersebut error karena API-nya tidak jalan. API tersebut error karena versi PHP terlalu tinggi untuk frameworknya, sehingga ada dua lib dari framework yang tidak jalan. Solusinya, aku harus downgrade versi lib yang dipakai, menggunakan composer. Sayangnya, ketika aku jalankan composer install maupun composer update muncul error Fatal error: Allowed memory size of 1610612736 bytes exhausted (tried to allocate 4096 bytes).</p>
<p>Mungkinkah RAM servernya habis? rasanya mustahil karena yang bersangkutan sewa shared hosting yang cukup mahal. Ternyata masalahnya adalah pada alokasi memory untuk php. Kalau seperti ini, solusi untuk Fatal error: Allowed memory size of 1610612736 bytes exhausted (tried to allocate 4096 bytes) sangatlah mudah, cukup jalanin composer dengan cara berikut:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">php -d memory_limit=-1 /usr/local/bin/composer install
</span><span>
</span><span style="color:#282828;">atau
</span><span>
</span><span style="color:#282828;">php -d memory_limit=-1 /usr/local/bin/composer update
</span></code></pre>
<p>Gitu aja.</p>
Let's Encrypt Wildcard SSL Cert Menggunakan Certbot Dan Cloudflare
2020-12-16T15:55:26+07:00
2020-12-16T15:55:26+07:00
Unknown
https://www.sumarsono.com/lets-encrypt-wildcard-ssl-cert-menggunakan-certbot-dan-cloudflare/
<p>Wildcard SSL Cert merupakan SSL Cert yang bisa dipakai untuk semua sub domain dari domain tertentu. Misalnya aku punya <a href="https://sumarsono.com">sumarsono.com</a>, ketika aku punya wildcard SSL Cert *.sumarsono.com, maka semua sub domain dibawah sumarsono.com dapat memakai certificate ssl tersebut. Tujuan dari wildcard SSL Cert ini, salah satunya untuk mengejar praktis, dan menghemat kuota SSL cert. Untuk sub domain dalam sekala kecil, tentu tidak begitu terasa manfaatnya, tapi untuk sub domain skala besar benar-benar terasa manfaatnya.</p>
<p>Cloudflare (dalam konteks kasus artikel ini) merupakan penyedia free dns hosting. Aku memakai cloudflare untuk panel domain-domain yang aku pakai. Beli domain dimanapun aku selalu pakai NS cloudflare. Untuk memudahkan manajemen, dikumpulkan di satu tempat.</p>
<p>Let's encrypt dalah Otoritas Sertifikasi (CA) yang gratis, terotomatisasi dan terbuka, ada untuk keuntungan publik. Mereka adalah layanan yang disediakan oleh <a href="https://www.abetterinternet.org/">Internet Security Research Group (ISRG)</a>. Mereka memberikan sertifikat yang diperlukan untuk menaktifkan HTTPS (SSL/TLS) pada web , secara gratis, semudah mungkin. </p>
<p>Cerbot merupakan tool untuk mendapatkan SSL Cert dari Let's Encrypt.</p>
<p>Untuk mendapatkan wildcard SSL Let's encrypt menggunakan Cerbot dan Cloudflare caranya sangat mudah. Satu-satunya challenge untuk mendapatkan wildcard SSL let's encrypt adalah lewat DNS, kita tidak bisa pakai http challenge maupun tls challenge. </p>
<p>Proses mendapatkan wildcard SSL Let's encrypt menggunakan Cerbot dan Cloudflare bisa manually, add/update TXT record yang diminta oleh Let's Encrypt secara manual. Bisa juga otomatis menggunakan DNS plugin. Aku lebih memilih yang otomatis, biar tidak repot add/update DNS record secara manual.</p>
<p>Pertama, aku harus genetate Token cloudflare khusus untuk edit Zone DNS. <strong>Login ke CF > My Profile > API Tokens > Create Token > Edit Zone DNS (Use template)</strong></p>
<p><img src="https://telegra.ph/file/2c20a71a63c2e4dafd74f.png" alt="Create token CF" /></p>
<ol>
<li>Permission-nya adalah Edit.</li>
<li>Zone silahkan pilih nama domain.</li>
<li>IP filter, diisi ip public server, goalnya untuk membatasi token hanya bisa dipakai oleh server terpilih.</li>
</ol>
<p>Kalau sudah diisi, lanjut Continue to summary dan create token, kemudian copy simpan token tsb baik-baik. Lanjut SSH ke server dan eksekusi perintah untuk install cerbot dan plugin dns-nya</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">sudo apt install certbot python3-certbot-dns-cloudflare
</span></code></pre>
<p>Aku masukin token cloudflare ke server</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">sudo mkdir /root/.secrets </span><span style="color:#b23c15;">&& </span><span>\
</span><span style="color:#282828;">sudo touch /root/.secrets/cloudflare.ini </span><span style="color:#b23c15;">&& </span><span>\
</span><span style="color:#282828;">sudo chmod 0600 /root/.secrets/cloudflare.ini </span><span style="color:#b23c15;">&& </span><span>\
</span><span style="color:#282828;">sudo nano /root/.secrets/cloudflare.ini
</span></code></pre>
<p>Paste token tadi ke dalam file tsb dengan format:</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">dns_cloudflare_api_token</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">paste-token-cf-di-sini
</span></code></pre>
<p>Kemudian aku dapatkan wildcard ssl cert dari let's encrypt dengan coomand:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">sudo certbot certonly --dns-cloudflare --dns-cloudflare-credentials /home/root/.secrets/cloudflare.ini -d </span><span style="color:#79740e;">"sumarsono.com"</span><span style="color:#282828;"> -d </span><span style="color:#79740e;">"*.sumarsono.com"
</span></code></pre>
<p>Setelah sukses, aku bisa verifikasi:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">sudo certbot certificates
</span></code></pre>
<p>Hasilnya:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">certbot certificates
</span><span style="color:#282828;">Saving debug log to /var/log/letsencrypt/letsencrypt.log
</span><span>
</span><span style="color:#282828;">Found the following certs:
</span><span> </span><span style="color:#282828;">Certificate Name: sumarsono.com
</span><span> </span><span style="color:#282828;">Domains: sumarsono.com </span><span style="color:#b23c15;">*</span><span style="color:#282828;">.sumarsono.com
</span><span> </span><span style="color:#282828;">Expiry Date: 2021-03-16 07:52:56+00:00 (VALID: 89 days</span><span>)
</span><span> </span><span style="color:#282828;">Certificate Path: /etc/letsencrypt/live/sumarsono.com/fullchain.pem
</span><span> </span><span style="color:#282828;">Private Key Path: /etc/letsencrypt/live/sumarsono.com/privkey.pem
</span></code></pre>
<p>Dengan begini wildcard SSL cert let's encrypt sudah aku dapatkan dan bisa dipakai. Contoh hasilnya adalah ini, aku gak generate ssl cert untuk subdomain email, tapi subdomain email tersebut ssl certnya valid karena memakai wildcard ssl cert</p>
<p><img src="https://telegra.ph/file/21ac31fc783f779f1713d.png" alt="wildcard ssl in action" /></p>
<p>Cool~</p>
Menambahkan Trackpad Gesture Ke Manjaro Linux
2020-12-16T09:11:55+07:00
2020-12-16T09:11:55+07:00
Unknown
https://www.sumarsono.com/menambahkan-trackpad-gesture-ke-manjaro-linux/
<p>Distro linux dengan kemampuan trackpad gesture tentu akan menyenangkan. Haha. Bayangkan swipe 3 jari ke kanan/kiri untuk switch virtualdesktop/workspace. Praktis. Bayangkan bisa swipe 3 jari up/down untuk membuka Gnome activites. Praktis. Terlebih untuk user yang terbiasa menggunakan gesture di Macbook. Meskipun tidak sama, tapi setidaknya mengobati sedikit kerinduan mereka.</p>
<p>Perkenalkan <a href="https://github.com/bulletmark/libinput-gestures">libinput-gesture</a>, </p>
<blockquote>
<p><a href="https://github.com/bulletmark/libinput-gestures/">Libinput-gestures</a> is a utility which reads <a href="https://wayland.freedesktop.org/libinput/doc/latest/gestures.html">libinput gestures</a> from your touchpad and maps them to gestures you configure in a configuration file. Each gesture can be configured to activate a shell command which is typically an <a href="https://www.semicomplete.com/projects/xdotool/"><em>xdotool</em></a> command to action desktop/window/application keyboard combinations and commands. See the examples in the provided <code>libinput-gestures.conf</code> file. My motivation for creating this is to use triple swipe up/down to switch workspaces, and triple swipe right/left to go backwards/forwards in my browser, as per the default configuration.</p>
</blockquote>
<p>libinput gesture ini keren, aku jadi bisa menambahkan fungsi baru ke trackpad. Konfigurasi libinput-gesture yang aku sukai:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span># Move to next workspace
</span><span>gesture swipe left 3 _internal ws_up
</span><span>
</span><span># Move to prev workspace
</span><span>gesture swipe right 3 _internal ws_down
</span><span>
</span><span># Activities
</span><span>gesture swipe up 3 xdotool key super+s
</span><span>gesture swipe down 3 xdotool key super+s
</span></code></pre>
<p>Cus ke laman <a href="https://github.com/bulletmark/libinput-gestures">github libinput-gesture</a>, dan install. Gak nyesel.</p>
Macos Catalina Display Port/Hdmi Sound Control
2020-12-14T10:04:57+07:00
2020-12-14T10:04:57+07:00
Unknown
https://www.sumarsono.com/macos-catalina-display-port-hdmi-sound-control/
<p><img src="https://telegra.ph/file/9fc2d61dd8aa49fa61bfa.png" alt="eqMac" /></p>
<p>MacOS by default tidak bisa mengontrol volume untuk perangkat yang tersambung lewat mini display port. Ketika masuk SysPref akan muncul "The selected device has no output control". Hal ini menjadi masalah ketika aku mau pakai sound output yang ada di monitor external. Solusi untuk hal ini adalah dengan memakai aplikasi pihak ketiga yang membuat kita bisa mengatur volume sound display port. </p>
<p>Beruntung ada aplikasi gratis dengan kode sumber terbuka, namanya <a href="https://eqmac.app">eqMac</a>. Dengan bantuan eqMac, aku jadi bisa mengatur volume sound output display port. Bonus equalizer.</p>
Dns Over Tls Pakai Systemd Resolved
2020-12-08T17:54:11+07:00
2020-12-08T17:54:11+07:00
Unknown
https://www.sumarsono.com/dns-over-tls-pakai-systemd-resolved/
<p>Systemd Resolved mendukung Dns over TLS (DoT), setupnya juga sangat mudah. Berkat ini aku meninggalkan cloudflared. Untuk menggunakan DoT systemd-resolved, caranya sebagai berikut:</p>
<p>Edit berkas <code>/etc/systemd/resolved.conf</code>, ubah isinya menjadi</p>
<p>bash
[Resolve]
DNS=1.1.1.1
DNSOverTLS=yes
DNSSEC=yes
FallbackDNS=8.8.8.8 8.8.4.4
Domains=~.</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>
</span><span>Kemudian restart dan enable servicenya
</span><span>
</span><span>```bash
</span><span>sudo systemctl restart systemd-resolved
</span><span>sudo systemctl enable systemd-resolved
</span></code></pre>
<p>Selesai, udah gitu aja. Btw aku pakai Manjaro Linux, distro lain silakan menyesuaikan.</p>
<p>Test hasilnya, DNS Secured:
<img src="https://telegra.ph/file/ada5ec9f1a9e179017556.png" alt="DoT Test" /></p>
<p><a href="https://wiki.archlinux.org/index.php/Systemd-resolved">Referensi systemd-resolved</a></p>
Relay Email Melalui Amazon Simple Email Service
2020-12-05T09:27:41+07:00
2020-12-05T09:27:41+07:00
Unknown
https://www.sumarsono.com/relay-email-melalui-amazon-simple-email-service/
<p>Ngurus email server itu PITA, pain in the **s. Install dan setup-nya sih gampil, semudah membalik telapak tangan. Tapi maintenance ini yang meh setengah mati. Memastikan email terkirim dan masuk ke INBOX tujuan, itu sulit. Apalagi bagi pemain kecil yang sewa dedicated IP saja tidak sanggup tapi ngotot bikin email server sendiri. Seriously, beli aja email account ke pemain besar, lebih reliable dan membuat hidup damai. Modal 4-10 USD sudah dapat 1 mail account untuk 1 bulan.</p>
<p>Lain cerita ya kalau for shake of learning, kalau untuk belajar ya hajar aja setup mail server. Worth it kok, ilmu yang Bisa dipelajari dari email server ada buanyak. Satu tahun aja gak akan cukup untuk melahap ilmu di mail server. Bukan sekedar install and forget ya.</p>
<p>Udah basa-basinya, AWS SES itu layanan email dari Amazon yang cukup menarik karena harga murah. Dulu aku tidak tertarik untuk mencoba AWS SES karena belum ada di region Asia Pacific (Singapore). Nah belum lama ini, tepatnya bulan juli 2020 si <a href="https://aws.amazon.com/about-aws/whats-new/2020/07/amazon-ses-available-ohio-singapore-tokyo-seoul-regions/">AWS mengumumkan kalau SES sudah ada di Singapore</a>. Berikut ini adalah skrinsut <a href="https://aws.amazon.com/ses/pricing/">harga amazon ses</a> untuk region Singapore:</p>
<p><img src="https://telegra.ph/file/5698ab8b4778b73edc8b7.png" alt="Harga AWS SES Singapore" /></p>
<p>Murah meriah ya menurut saya. Cocok untuk kebutuhan teman-teman yang sedang belajar untuk relay email, atau send bulk email dari aplikasi lewat SMTP.</p>
<p>Setup amazon ses ini gampil, straight forward:</p>
<ol>
<li>Login ke console AWS</li>
<li>Pergi ke menu SES</li>
<li>Add domain + verifikasi domain</li>
<li>Generate DKIM</li>
<li>Tambah dan verifikasi email</li>
<li>Generate SMTP Credential</li>
<li>Copas atau Download SMTP credetial yang telah dibuat</li>
</ol>
<p>Selesai, cuma itu aja buat setup amazon ses. Selanjutnya untuk relay outbound email kita lewat amazon ses tinggal setup sender dependent transport di email server kita, cuma masukin smtp host milik aws ses, portnya, user smtp dan pass smtp. Setup relay ke aws ses selesai.</p>
<p>Lanjut tes hasil relaynya, berikut ini ss email yang di relay lewat SES</p>
<p><img src="https://telegra.ph/file/bdb7e9ff1f92b40254e96.png" alt="Email dari SES" /></p>
<p>Kalau di cek original messagenya, maka akan tampak:</p>
<p><img src="https://telegra.ph/file/bd9e312904e203e84cb96.png" alt="Original Message SES" /></p>
Podman, Buildah, Crun, Cgroupv2 Manjaro Linux
2020-12-03T11:34:46+07:00
2020-12-03T11:34:46+07:00
Unknown
https://www.sumarsono.com/podman-buildah-crun-cgroupv2-manjaro-linux/
<p>Manjaro linux by default membawa cgroup v1 dan v2, tapi yang diaktifkan adalah cgroup v1. Ketika hendak belajar tentang podman, buildah, dan crun maka kita perlu mengatifkan cgroupv2. Mengaktifkan cgroupv2 di Manjaro Linux ini mudah, semudah membalik telapak tangan.</p>
<p>Untuk mengaktifkan cgroupv2 di Manjaro Linux, pertama edit parameter kernel</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">sudo nano /etc/default/grub
</span></code></pre>
<p>cari line <code>GRUB_CMDLINE_LINUX_DEFAULT=</code>, kemudian tambahkan parameter <code>cgroup_no_v1=all</code></p>
<p>Hasil akhirnya kira-kira begini</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">GRUB_DEFAULT</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">saved
</span><span style="color:#282828;">GRUB_TIMEOUT</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">3
</span><span style="color:#282828;">GRUB_TIMEOUT_STYLE</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">menu
</span><span style="color:#282828;">GRUB_DISTRIBUTOR</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">"Manjaro"
</span><span style="color:#282828;">GRUB_CMDLINE_LINUX_DEFAULT</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">"apparmor=1 security=apparmor resume=UUID=587103ec-55a5-4f4d-9c9d-53c191644c67 udev.log_priority=3 mitigations=off cgroup_no_v1=all"
</span><span>
</span><span style="color:#b23c15;"><</span><span>redacted </span><span style="color:#282828;">krn kepanjangan</span><span style="color:#b23c15;">>
</span></code></pre>
<p>Kemudian, update grub dan reboot manjaro</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">sudo update-grub
</span><span style="color:#282828;">systemctl reboot
</span></code></pre>
<p>Sekarang, Manjaro Linux sudah pakai cgroupv2. Selanjutnya, aku akan memasang podman, buildah, dan crun</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">sudo pacman -S buildah podman crun fuse-overlayfs
</span></code></pre>
<p>Kemudian, untuk run <em>unprivileged container</em> kita harus set <code>subuid</code> dan <code>subguid</code> untuk user dan group kita</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#b57614;">echo </span><span style="color:#79740e;">"$(</span><span style="color:#282828;">whoami</span><span style="color:#79740e;">):100000:65536" </span><span style="color:#b23c15;">| </span><span style="color:#282828;">sudo tee -a /etc/subuid
</span><span style="color:#b57614;">echo </span><span style="color:#79740e;">"$(</span><span style="color:#282828;">whoami</span><span style="color:#79740e;">):100000:65536" </span><span style="color:#b23c15;">| </span><span style="color:#282828;">sudo tee -a /etc/subgid
</span></code></pre>
<p>Reboot Manjaro Linux</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">systemctl reboot
</span></code></pre>
<p>Terakhir apakah podman sudah pakai cgroupv2</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">podman info --debug
</span><span>
</span><span style="font-style:italic;color:#928374;">#output
</span><span style="color:#282828;">host:
</span><span> </span><span style="color:#282828;">arch: amd64
</span><span> </span><span style="color:#282828;">buildahVersion: 1.16.1
</span><span> </span><span style="color:#282828;">cgroupManager: systemd
</span><span> </span><span style="color:#282828;">cgroupVersion: v2
</span><span> </span><span style="color:#282828;">conmon:
</span><span> </span><span style="color:#282828;">package: Unknown
</span><span> </span><span style="color:#282828;">path: /usr/bin/conmon
</span><span> </span><span style="color:#282828;">version: </span><span style="color:#79740e;">'conmon version 2.0.21, commit: 35a2fa83022e56e18af7e6a865ba5d7165fa2a4a'
</span><span> </span><span style="color:#282828;">cpus: 4
</span><span> </span><span style="color:#282828;">distribution:
</span><span> </span><span style="color:#282828;">distribution: manjaro
</span><span> </span><span style="color:#282828;">version: unknown
</span><span> </span><span style="color:#282828;">eventLogger: journald
</span><span> </span><span style="color:#282828;">hostname: x240
</span><span> </span><span style="color:#282828;">idMappings:
</span><span> </span><span style="color:#282828;">gidmap:
</span><span> </span><span style="color:#282828;">- container_id: 0
</span><span> </span><span style="color:#282828;">host_id: 1000
</span><span> </span><span style="color:#282828;">size: 1
</span><span> </span><span style="color:#282828;">- container_id: 1
</span><span> </span><span style="color:#282828;">host_id: 100000
</span><span> </span><span style="color:#282828;">size: 65536
</span><span> </span><span style="color:#282828;">uidmap:
</span><span> </span><span style="color:#282828;">- container_id: 0
</span><span> </span><span style="color:#282828;">host_id: 1000
</span><span> </span><span style="color:#282828;">size: 1
</span><span> </span><span style="color:#282828;">- container_id: 1
</span><span> </span><span style="color:#282828;">host_id: 100000
</span><span> </span><span style="color:#282828;">size: 65536
</span><span>
</span><span style="color:#b23c15;"><</span><span>redated </span><span style="color:#282828;">krn panjang</span><span style="color:#b23c15;">>
</span></code></pre>
<p>Selanjutnya, kita harus set image registry yg akan dipakai oleh buildah, krn defaultnya kosong dan menyebabkan buildah tidak bisa pull image</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">sudo nano /etc/containers/registries.conf
</span></code></pre>
<p>Tambahkan</p>
<pre data-lang="yaml" style="background-color:#fcf0ca;color:#282828aa;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span>[</span><span style="color:#79740e;">registries.search</span><span>]
</span><span style="color:#79740e;">registries = ['docker.io', 'registry.fedoraproject.org', 'quay.io', 'registry.access.redhat.com', 'registry.centos.org']
</span></code></pre>
<p>Tes buildah pull image</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">buildah pull nginx:alpine
</span><span>
</span><span style="font-style:italic;color:#928374;"># output
</span><span style="color:#282828;">Completed short name </span><span style="color:#79740e;">"nginx"</span><span style="color:#282828;"> with unqualified-search registries (origin: /etc/containers/registries.conf</span><span>)
</span><span style="color:#282828;">Getting image source signatures
</span><span style="color:#282828;">Copying blob 188c0c94c7c5 skipped: already exists
</span><span style="color:#282828;">Copying blob af69a9b963c8 done
</span><span style="color:#282828;">Copying blob 7d856acdaa9c done
</span><span style="color:#282828;">Copying blob a0d3c6e28e6d done
</span><span style="color:#282828;">Copying blob 617561f33ec6 done
</span><span style="color:#282828;">Copying config 98ab35023f done
</span><span style="color:#282828;">Writing manifest to image destination
</span><span style="color:#282828;">Storing signatures
</span><span style="color:#282828;">98ab35023fd67311434b73434d860138a203ab5851fcc9a7161510d5c43fc755
</span></code></pre>
<p>Tes podman run image</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">podman run -p 1992:80 nginx:alpine
</span><span>
</span><span style="font-style:italic;color:#928374;"># output
</span><span style="color:#282828;">/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
</span><span style="color:#282828;">/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
</span><span style="color:#282828;">/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
</span><span style="color:#282828;">10-listen-on-ipv6-by-default.sh: Getting the checksum of /etc/nginx/conf.d/default.conf
</span><span style="color:#282828;">10-listen-on-ipv6-by-default.sh: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
</span><span style="color:#282828;">/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
</span><span style="color:#282828;">/docker-entrypoint.sh: Configuration complete</span><span style="color:#b23c15;">; </span><span style="color:#282828;">ready for start up
</span><span>
</span></code></pre>
<p>Sekian, dan terima gaji.</p>
Memasang SSL Cert Cloudflare Ke Cpanel
2020-12-02T19:11:22+07:00
2020-12-02T19:11:22+07:00
Unknown
https://www.sumarsono.com/memasang-ssl-cert-cloudflare-ke-cpanel/
<p>Ketika kita mengelola domain menggunakan cloudflare, kita mendapatkan free SSL certificate. Ini menguntungkan kita, kita gak perlu repot-repot untuk generate ssl cert. Cloudflare juga mendukung SSL/TLS mode strict, yakni komunikasi server cloudflare dengan server kita dalam mode encrypted, engga plain.</p>
<p><img src="https://telegra.ph/file/af5024cbd3891bce63b3d.png" alt="Cloudflare Strict Mode" /></p>
<p>Untuk mengaktifkan mode strict, kita perlu memasang Origin Cert cloudflare ke server kita. Dalam konteks saat ini yakni kita pasang ke cPanel.</p>
<p>Pertama, kita harus generate origin cert cloudflare. Login ke <a href="https://dash.cloudflare.com">dashboard cloudflare</a> kemudian pergi ke menu <strong>SSL/TLS > Origin Server</strong> klik <strong>Create Certificate</strong></p>
<p>Catat dan simpan baik-baik Private Key dan Certificate hasil generate.</p>
<p>Contoh origin cert hasil generate:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>-----BEGIN CERTIFICATE-----
</span><span>MIIEqDCCA5CgAwIBAgIUNh4nVD4aM7DnC0LZuYra6yqVHC0wDQYJKoZIhvcNAQEL
</span><span>bla bla bla bla
</span><span>Wdn8YIeT6WANwycux64Nef1SqKBlpvE+lSrgUIxX627BJ0hRzZWMcFIeS7E=
</span><span>-----END CERTIFICATE-----
</span></code></pre>
<p>Contoh private key hasil generate:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>-----BEGIN PRIVATE KEY-----
</span><span>MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDVwOD7TEO5cOBr
</span><span>bla bla bla bla
</span><span>VO1M23IVpB5VPYvfltW7KVF1
</span><span>-----END PRIVATE KEY-----
</span></code></pre>
<p>Kedua, pasang certificate dan private key tadi ke cPanel. Login ke cPanel, <strong>cari menu SSL/TLS</strong>.</p>
<p>Untuk memasang private key, klik menu <strong>SSL/TLS > Private Key (KEY)</strong> kemudian copas privkey cloudflare kesana dan klik <strong>Save</strong></p>
<p>Untuk memasang Certificates, klik menu <strong>SSL/TLS > Certificates (CRT)</strong> kemudian copas cert cloudflare kesana dan klik <strong>Save</strong></p>
<p>Ketiga, pasang SSL tadi ke website. Caranya masuk ke menu <strong>SSL/TLS > Install and Manage SSL for your site (HTTPS)</strong>, kemudian click tombol <strong>Browse Certificates</strong> dan pilih SSL yang tadi disimpan pada langkah nomer 2. Kemudian scroll kebawah, cari <strong>Certificate Authority Bundle: (CABUNDLE)</strong> ganti isinya dengan CABUNDLE milik cloudflare, bisa di <a href="https://support.cloudflare.com/hc/article_attachments/360037885371/origin_ca_rsa_root.pem">download dari sini</a>. Kemudian klik <strong>Install Certificate</strong></p>
<p>Terakhir, kembali ke dashboard cloudlare dan aktifkan SSL/TLS FULL (Strict), setelah itu cek web kita, pasti sudah pakai SSL Cloudflare dalam mode full strict. Jangan lupa aktifkan awan kuning di domain kita.</p>
<p><img src="https://telegra.ph/file/8b79eb53d7f74d51ac062.png" alt="Website use cloudflare ssl" /></p>
Kirim Email Dari Terminal Mac Os Catalina
2020-11-17T22:02:19+07:00
2020-11-17T22:02:19+07:00
Unknown
https://www.sumarsono.com/kirim-email-dari-terminal-mac-os-catalina/
<p>Kita bisa mengirim email dari terminal Mac OS Catalina. Mac OS catalina by default sudah membawa postfix, tapi menurutku postfix terlalu overkill untuk kebutuhan sekedar kirim email dari terminal yang di relay ke gmail. Oleh sebab itu, aku akan pakai msmtp. Msmtp sendiri merupakan SMTP client yg cukup kecil, dan konfigurasinya sangat sederhana. Untuk memasang msmtp di Mac OS Catalina, syaratnya harus sudah pasang homebrew.</p>
<p>Berikut ini adalah cara untuk memasang msmtp dan konfigurasi msmtp relay ke gmail.</p>
<p>Pertama, aku bikin app password di <a href="https://myaccount.google.com/apppasswords">https://myaccount.google.com/apppasswords</a></p>
<p>Kedua, aku pasang openssl dan msmtp pakai <code>brew</code></p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#9d0006;">export </span><span style="color:#282828;">HOMEBREW_NO_AUTO_UPDATE</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">1
</span><span style="color:#282828;">brew install openssl@1.1
</span><span style="color:#282828;">brew install msmtp
</span></code></pre>
<p>Ketiga, aku bikin konfigurasi msmtp</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">sudo vim /usr/local/Cellar/msmtp/1.8.12/etc/msmtprc
</span></code></pre>
<p><code>1.8.12</code> itu menyesuaikan dengan versi msmtp yang terinstall</p>
<p>Isi dari file <code>/usr/local/Cellar/msmtp/1.8.12/etc/msmtprc</code></p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>defaults
</span><span>tls on
</span><span>auth on
</span><span>tls_trust_file /usr/local/etc/openssl@1.1/cert.pem
</span><span>logfile ~/.msmtp.log
</span><span>
</span><span>account gmail
</span><span>host smtp.gmail.com
</span><span>port 587
</span><span>from your-email@gmail.com
</span><span>user your-email@gmail.com
</span><span>password your-generated-app-password
</span><span>account default : gmail
</span></code></pre>
<p>Terakhir, set alias sendmail menjadi msmtp</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#b57614;">echo</span><span style="color:#282828;"> set sendmail=</span><span style="color:#79740e;">"/usr/local/bin/msmtp" </span><span style="color:#b23c15;">> </span><span style="color:#282828;">~/.mailrc
</span></code></pre>
<p>Selesai konfigurasi msmtp, aku test</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">date </span><span style="color:#b23c15;">| </span><span style="color:#282828;">mail -s </span><span style="color:#79740e;">"Dikirim dari Catalina"</span><span style="color:#282828;"> alamat-email-tujuan@gmail.com
</span></code></pre>
<p>Jreng, email masuk ke inbox alamat-email-tujuan.</p>
<p>Cool~</p>
Fedora 33 Install Sublime Text
2020-11-05T14:06:34+07:00
2020-11-05T14:06:34+07:00
Unknown
https://www.sumarsono.com/fedora-33-install-sublime-text/
<p>Install Sublime Text di Fedora sangat mudah. Pasang GPG key sublime text, tambahkan repo sublime text, install sublime text, pakai sublime text. Semudah itu.</p>
<p><img src="https://telegra.ph/file/f819ea4aa7e3906cd088c.png" alt="Sublime Text Fedora 33" /></p>
<p>Install GPG key sublime text:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">sudo rpm -v --import https://download.sublimetext.com/sublimehq-rpm-pub.gpg
</span></code></pre>
<p>Tambahkan repo sublime text ke fedora 33:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">sudo dnf config-manager --add-repo https://download.sublimetext.com/rpm/stable/x86_64/sublime-text.repo
</span></code></pre>
<p>Install sublime text di fedora 33:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">sudo dnf install sublime-text
</span></code></pre>
Google Chrome Open Profile Selector by Default
2020-11-04T19:30:32+07:00
2020-11-04T19:30:32+07:00
Unknown
https://www.sumarsono.com/google-chrome-open-profile-selector-by-default/
<p>Google chrome mendukung multiple profile. Ini fitur yang bagus menurutku, aku bisa memisahkan profile berdasarkan kebutuhan, pekerjaan. Tampilan jendela untuk memilih profile juga cakep.</p>
<p><img src="https://telegra.ph/file/c12fc336a6afad0da22e8.png" alt="Chrome profile selector" /></p>
<p>Aku ingin ketika klik aplikasi Chrome muncul jendela itu. Jadi bisa langsung memilih profile mana yang mau dipakai.
Caranya cukup mudah, edit Launcher chrome menjadi:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>/usr/bin/google-chrome-stable %U --profile-directory="Guest Profile"
</span></code></pre>
<p>Udah git aja, pas buka chrome langsung nongol jendela untuk milih profile.</p>
<p>Cool~</p>
Fedora 33 Rpm Fusion
2020-11-04T19:15:42+07:00
2020-11-04T19:15:42+07:00
Unknown
https://www.sumarsono.com/fedora-33-rpm-fusion/
<p>Memasang repo rpm fusion di fedora 33 sangat mudah, cukup eksekusi dua baris perintah:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo dnf install https://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm
</span><span>sudo dnf install https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm
</span></code></pre>
<p>Dengan begitu, dua rpm fusion free dan non free akan terpasang sesuai versi Fedora.</p>
<p>Haha.</p>
Fix Aplikasi Gak Terindex Spotlight
2020-10-30T10:06:48+07:00
2020-10-30T10:06:48+07:00
Unknown
https://www.sumarsono.com/fix-aplikasi-gak-terindex-spotlight/
<p>Spotlight ini fitur pencarian punya mac os, biasanya cukup tekan command+space, nongol pencarian spotlight. Bisa nyari app, file, folder, bookmark, definition.</p>
<p>Yang aneh pagi ini adalah, pas aku buka spotlight dan nyari sublime, engga nongol aplikasi sublime text, nyari app lain juga engga nongol, tapi nyari file bisa nongol.
Ternyata fixnya sangat mudah, rebuild mds metadata:</p>
<ul>
<li>SysPref > Spotlight</li>
<li>Privacy Tab, klik tanda +</li>
<li>Add disk mac</li>
<li>setelah tertambahkan, klik tanda -</li>
</ul>
<p>Boom, reindex selesai. command+space cari aplikasi dah nongol lagi.</p>
<p>Hahahaha</p>
Disable Partisi Swap Manjaro
2020-10-15T07:33:41+07:00
2020-10-15T07:33:41+07:00
Unknown
https://www.sumarsono.com/disable-partisi-swap-manjaro/
<p>Jaman dahulu kala, untuk disable swap cuku edit fstab dan comment atau hapus entry swap. Contohnya seperti ini:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">cat /etc/fstab
</span><span>
</span><span style="font-style:italic;color:#928374;"># output
</span><span style="font-style:italic;color:#928374;"># /etc/fstab: static file system information.
</span><span style="font-style:italic;color:#928374;">#
</span><span style="font-style:italic;color:#928374;"># Use 'blkid' to print the universally unique identifier for a device; this may
</span><span style="font-style:italic;color:#928374;"># be used with UUID= as a more robust way to name devices that works even if
</span><span style="font-style:italic;color:#928374;"># disks are added and removed. See fstab(5).
</span><span style="font-style:italic;color:#928374;">#
</span><span style="font-style:italic;color:#928374;"># <file system> <mount point> <type> <options> <dump> <pass>
</span><span style="color:#282828;">UUID</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">F520-C9DE </span><span style="color:#282828;">/boot/efi vfat umask=0077 0 2
</span><span style="color:#282828;">UUID</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">dd64c675-f071-4db1-9d5c-981de854619c </span><span style="color:#282828;">/ ext4 defaults,noatime 0 1
</span><span style="font-style:italic;color:#928374;">#UUID=95aad2f9-fe0a-4646-ac69-cf50f9c8853e swap swap defaults,noatime 0 2
</span><span style="color:#282828;">tmpfs /tmp tmpfs defaults,noatime,mode=1777 0 0
</span></code></pre>
<p>Namun cara tersebut sudah tidak berlaku, khususnya di Manjaro. Aku mencoba disable swap Manjaro dengan edit fstab kemudian reboot, swap masih jalan dan berfungsi. Hal tersebut terjadi sejak systemd 'menyerang' dunia linux. Yep, sekarang swap di Manjaro Linux di handle oleh systemd. Untuk disable swap di Manjaro Linux, kita harus mulai dari melihat unit systemd mana yang mengatur swap.</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">systemctl --type swap
</span></code></pre>
<p>Akan kelihatan unit systemd yang mengatur swap. Untuk disable swap di manjaro linux, maka kita perlu disable dan mask unit tersebut.</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">sudo systemctl disable --now dev-sda4.swap
</span><span style="color:#282828;">sudo systemctl mask dev-sda4.swap
</span><span style="color:#282828;">systemctl reboot
</span></code></pre>
<p>Catatan: <code>dev-sda4.swap</code> disesuaikan dengan output dari <code>systemctl --type swap</code>.</p>
<p>Selesai, sekarang partisi swap manjaro linux sudah terdisable dengan benar.</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">free -h
</span><span> </span><span style="color:#282828;">total used free shared buff/cache available
</span><span style="color:#282828;">Mem: 7,7Gi 1,5Gi 4,3Gi 261Mi 1,9Gi 5,7Gi
</span><span style="color:#282828;">Swap: 0B 0B 0B
</span></code></pre>
<p>Cool~</p>
Flash Xiaomi Dari Linux
2020-09-30T06:55:13+07:00
2020-09-30T06:55:13+07:00
Unknown
https://www.sumarsono.com/flash-xiaomi-dari-linux/
<p>Flash hp xiaomi dari linux sangatlah mudah, karena dari pihak xiaomi ngasih berkas yang bisa dieksekusi dari linux. Untuk flash xiaomi, langkahnya adalah sebagai berikut:</p>
<p>Pertama, masuk fastboot. Kalau hp dari posisi Off maka cukup tekan tombol volume down + power. Kalau dari kondisi hp On, cukup aktifkan adb dari mode developer, kemudian di linux eksekusi:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">sudo adb devices </span><span style="font-style:italic;color:#928374;"># di hp akan muncul permintaan auth, di allow.
</span><span style="color:#282828;">sudo adb reboot bootloader
</span></code></pre>
<p>Setelah masuk bootloader/fastboot, kita masuk ke folder hasil ekstract dari rom miui fastboot. Folder tsb isinya:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">flash_all.bat flash_all_lock.bat flash_all_lock.sh flash_factory.sh flash_gen_resparsecount misc.txt
</span><span style="color:#282828;">flash_all_except_storage.bat flash_all_lock_crc.bat flash_all.sh flash_gen_crc_list.py images
</span><span style="color:#282828;">flash_all_except_storage.sh flash_all_lock_crc.sh flash_factory.bat flash_gen_md5_list.py md5sum.xml
</span></code></pre>
<p>Untuk flash cukup eksekusi:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">sudo bash flash_all.sh
</span></code></pre>
<p>Tunggu sampai selesai, jangan cabut/senggol kabel usb hp yang ke pc.</p>
<p>Dan jreng, selesai flash hp xiaomi dari linux.</p>
<p>Cool~</p>
Mendapatkan Serial Number Windows Dari Linux
2020-09-29T16:00:07+07:00
2020-09-29T16:00:07+07:00
Unknown
https://www.sumarsono.com/mendapatkan-serial-number-windows-dari-linux/
<p>Jaman dulu, serial number windows ditempel pakai sticker COA. Jaman sekarang, sudah gak pakai model begitu. Laptop-laptop preinstalled windows udah gak ada tempelan sticker serial number windows. Jaman sekarang serial number windows ditulis di dalam chip BIOS/UEFI. Jadi engga usah khawatir serialnya terkelupas haha.</p>
<p>Terus caranya gimana kalau kita mau lihat serial windows yang ditulis di chip? kalau pakai linux gampil, satu baris perintah linux untuk membaca serial number windows yang terlulis di chip:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">sudo strings /sys/firmware/acpi/tables/MSDM </span><span style="color:#b23c15;">| </span><span style="color:#282828;">tail -1
</span></code></pre>
<p>Outputnya kurang lebih begini:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">7XXX-XXXXX-XXXXX-XXXXX-XXXXX
</span></code></pre>
<p>Sengaja di sensor, haha. Gampil kan.</p>
<p>Cool~</p>
Manjaro Fix Touchpad X240 Setelah Sleep
2020-09-29T13:17:01+07:00
2020-09-29T13:17:01+07:00
Unknown
https://www.sumarsono.com/manjaro-fix-touchpad-x240-setelah-sleep/
<p>Aku pakai Lenovo Thinkpad X240 dengan sistem operasi Manjaro. Manjaro merupakan distro linux turunan dari Arch linux. Thinkpad memang dikenal cukup bagus kompatibiltas terhadap distro linux. Ya benar saja, begitu install langsung work semua. Eh tunggu dulu, ada satu masalah serius. Touchpadnya mati pas bangun dari sleep. Hahaha.</p>
<p>Ini sih udah masti krn drivernya, Manjaro pakai xf86-input-libinput untuk driver touchpadnya. Coba pasang xf86-input-synpatic, jadi waras pas, bangun dari sleep tpuchpad engga mati tapi two finger scroll engga jalan. Yaudah, pakai libinput aja, synaptic aku hapus.</p>
<p>Masuk lebih dalam, libinput ini pakai module kernel psmouse. Pas bangun dari sleep, touchpad mati, ku coba:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">modprobe -r psmouse
</span><span style="color:#282828;">modprobe psmouse
</span></code></pre>
<p>Touchpad langsung jalan dengan normal. Oke, solusi ketemu. Tinggal tambahin ke systemd supaya di triger ketika sleep dan bangun.</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">sudo vim /lib/systemd/system-sleep/touchpad-fix
</span><span>
</span><span style="font-style:italic;color:#928374;"># isi dengan
</span><span style="font-style:italic;color:#928374;">#!/bin/sh
</span><span style="color:#9d0006;">case </span><span>$</span><span style="color:#282828;">1</span><span>/$</span><span style="color:#282828;">2 </span><span style="color:#9d0006;">in
</span><span> pre/</span><span style="color:#b23c15;">*</span><span style="color:#9d0006;">)
</span><span> </span><span style="color:#b57614;">echo </span><span style="color:#79740e;">"Going to $</span><span style="color:#282828;">2</span><span style="color:#79740e;">..."
</span><span> </span><span style="font-style:italic;color:#928374;"># Place your pre suspend commands here, or `exit 0` if no pre suspend action required
</span><span> </span><span style="color:#282828;">modprobe -r psmouse
</span><span> ;;
</span><span> post/</span><span style="color:#b23c15;">*</span><span style="color:#9d0006;">)
</span><span> </span><span style="color:#b57614;">echo </span><span style="color:#79740e;">"Waking up from $</span><span style="color:#282828;">2</span><span style="color:#79740e;">..."
</span><span> </span><span style="font-style:italic;color:#928374;"># Place your post suspend (resume) commands here, or `exit 0` if no post suspend action required
</span><span> </span><span style="color:#282828;">sleep 2
</span><span> </span><span style="color:#282828;">modprobe psmouse
</span><span> ;;
</span><span style="color:#9d0006;">esac
</span></code></pre>
<p>Kemudian jadikan executable</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">sudo chmod +x /lib/systemd/system-sleep/touchpad-fix
</span></code></pre>
<p>Selesai, tes sleep/hibernate dan bangunin, touchpad normal. Mantap.</p>
<p>Cool~</p>
Laravel Queue Pakai Pm2
2020-09-29T10:08:13+07:00
2020-09-29T10:08:13+07:00
Unknown
https://www.sumarsono.com/laravel-queue-pakai-pm2/
<blockquote>
<p>Laravel queues provide a unified API across a variety of different queue backends, such as Beanstalk, Amazon SQS, Redis, or even a relational database. Queues allow you to defer the processing of a time consuming task, such as sending an email, until a later time. Deferring these time consuming tasks drastically speeds up web requests to your application. -- <a href="https://laravel.com/docs/8.x/queues">laravel queue docs</a></p>
</blockquote>
<p>Oke jadi laravel itu punya fitur queue. Tapi daemonnya harus dijalankan manual pakai</p>
<pre data-lang="php" style="background-color:#fcf0ca;color:#282828aa;" class="language-php "><code class="language-php" data-lang="php"><span>php artisan queue:work
</span></code></pre>
<p>Ya kalau di dev mah gak masalah, kalau di production kan repot. Dari laravel ngasih contoh manage daemon pakai supervisor[d]. Tapi engga semua orang nyaman pakai supervisor[d]. Ada alternatif lain untuk menjalakan laravel queue, pakai PM2.</p>
<blockquote>
<p>PM2 is a daemon process manager that will help you manage and keep your application online 24/7 -- <a href="https://pm2.keymetrics.io/">pm2.keymetrics.io</a></p>
</blockquote>
<p>Setup daemon laravel queue pakai pm2 mudah banget, pertama install dulu pm2</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">npm install pm2 -g
</span></code></pre>
<p>Kemudian bikin definisi untuk proses pm2, aku beri nama <code>laravel-queue-worker.yaml</code></p>
<pre data-lang="yaml" style="background-color:#fcf0ca;color:#282828aa;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span style="font-weight:bold;color:#407959;">apps</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">laravel-queue-worker
</span><span> </span><span style="font-weight:bold;color:#407959;">script</span><span>: </span><span style="color:#79740e;">artisan
</span><span> </span><span style="font-weight:bold;color:#407959;">exec_mode</span><span>: </span><span style="color:#79740e;">fork
</span><span> </span><span style="font-weight:bold;color:#407959;">interpreter</span><span>: </span><span style="color:#79740e;">php
</span><span> </span><span style="font-weight:bold;color:#407959;">instances</span><span>: </span><span style="color:#8f3f71;">1
</span><span> </span><span style="font-weight:bold;color:#407959;">args</span><span>:
</span><span> - </span><span style="color:#79740e;">queue:work
</span><span> - </span><span style="color:#79740e;">--tries=5
</span><span> - </span><span style="color:#79740e;">--sleep=1
</span></code></pre>
<p>Selanjutnya kita start definisi tsb</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">pm2 start laravel-queue-worker.yaml
</span></code></pre>
<p>Hasilnya bisa di cek pakai</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">pm2 ps
</span><span>
</span><span style="font-style:italic;color:#928374;"># outputnya
</span><span style="color:#282828;">┌─────┬─────────────────────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐
</span><span style="color:#282828;">│ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ user │ watching │
</span><span style="color:#282828;">├─────┼─────────────────────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤
</span><span style="color:#282828;">│ 0 │ laravel-queue-worker │ default │ N/A │ fork │ 21657 │ 18h │ 0 │ online │ 0% │ 32.1mb │ suneo │ disabled │
</span><span style="color:#282828;">└─────┴─────────────────────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘
</span></code></pre>
<p>Langkah terakhir, enable auto start ketika mesin restart</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">pm2 startup
</span><span style="color:#282828;">pm2 save
</span></code></pre>
<p>Selesai</p>
Membuat Vanity Nameserver dns.he.net
2020-09-25T16:04:41+07:00
2020-09-25T16:04:41+07:00
Unknown
https://www.sumarsono.com/membuat-vanity-nameserver-dns-he-net/
<p>Vanity name server merupakan name server yang di branding pakai domain kita. DNS branding ini umumnya ya setup pakai bind9 di server. Bagi yang tidak punya server, berikut ini ada cara mudahnya. Tujuan dari vanity name server ini, supaya terlihat lebih profesional. Misalnya kita whois some-domain.com, maka akan muncul Name Server (NS), biasanya NS pakai milik domain registrar. Kalau pakai vanity name server, kita bisa masukin brand kita ketika di whois. Hasil akhir vanity name server adalah sebagai berikut:</p>
<p><img src="https://sumarsimages.files.wordpress.com/2020/09/vanity-name-server-sumarsono.com_.png" alt="whois sumarsono.com" /></p>
<p>dns.he.net merupakan provider manajemen dns <a href="http://he.net/">Hurricane Electric</a>. Mereka menawarkan panel untuk manajemen DNS, secara gratis (seperti cloudflare) dengan limit 50 domain. DNS record yang bisa dibuat di sana sangat banyak, mantap pokoknya.</p>
<p>Aku beli domain di <a href="https://porkbun.com/">porkbun.com</a> kemudian manajemen domainnya aku pindahkan ke <a href="https://dns.he.net/">dns.he.net</a> dengan cara mengganti name server di porkbun, name servernya ku ganti ke NS milik he.net. Default NS porkbun adalah sebagai berikut</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>curitiba.porkbun.com
</span><span>fortaleza.porkbun.com
</span><span>maceio.porkbun.com
</span><span>salvador.porkbun.com
</span></code></pre>
<p>Aku ganti menjadi:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>ns1.he.net
</span><span>ns2.he.net
</span><span>ns3.he.net
</span><span>ns4.he.net
</span><span>ns5.he.net
</span></code></pre>
<p>Penggantian NS umumnya memakan waktu 24 jam. Setelah selesai, dengan demikian maka manajemen dns sumarsono.com resmi pindah ke dns.he.net. Edit/Tambah/Delete record dilakukan lewat panel dns.he.net.</p>
<p>Untuk membuat vanity name server sangatlah mudah, pertama aku bikin A record di dns.he.net untuk NS yang akan kupakai nanti</p>
<table><thead><tr><th>DNS Record</th><th>Type</th><th>Value</th></tr></thead><tbody>
<tr><td>ns1.sumarsono.com</td><td>A</td><td>216.218.130.2</td></tr>
<tr><td>ns2.sumarsono.com</td><td>A</td><td>216.218.131.2</td></tr>
<tr><td>ns3.sumarsono.com</td><td>A</td><td>216.218.132.2</td></tr>
<tr><td>ns4.sumarsono.com</td><td>A</td><td>216.66.1.2</td></tr>
<tr><td>ns5.sumarsono.com</td><td>A</td><td>216.66.80.18</td></tr>
</tbody></table>
<p>IP Address tersebut diperoleh dari drill ns1..ns5.he.net</p>
<p>Kemudian aku bikin NS record di dns.he.net</p>
<table><thead><tr><th>DNS Record</th><th>Type</th><th>Value</th></tr></thead><tbody>
<tr><td>sumarsono.com</td><td>NS</td><td>ns1.sumarsono.com</td></tr>
<tr><td>sumarsono.com</td><td>NS</td><td>ns2.sumarsono.com</td></tr>
<tr><td>sumarsono.com</td><td>NS</td><td>ns3.sumarsono.com</td></tr>
<tr><td>sumarsono.com</td><td>NS</td><td>ns4.sumarsono.com</td></tr>
<tr><td>sumarsono.com</td><td>NS</td><td>ns5.sumarsono.com</td></tr>
</tbody></table>
<p>Hasilnya kira-kira begini</p>
<p><img src="https://sumarsimages.files.wordpress.com/2020/09/vanity-name-server-sumarsono.com-2.png" alt="Bikin A record dan NS record he.net" /></p>
<p>Setelah semua beres, aku harus registrasi glue record di porkbun. Glue record yang didaftarkan adalah ns1..ns5.sumarsono.com</p>
<table><thead><tr><th>Hostname</th><th>IP Address</th></tr></thead><tbody>
<tr><td>ns1</td><td>216.218.130.2</td></tr>
<tr><td>ns2</td><td>216.218.131.2</td></tr>
<tr><td>ns3</td><td>216.218.132.2</td></tr>
<tr><td>ns4</td><td>216.66.1.2</td></tr>
<tr><td>ns5</td><td>216.66.80.18</td></tr>
</tbody></table>
<p>Hasilnya seperti ini</p>
<p><img src="https://sumarsimages.files.wordpress.com/2020/09/vanity-name-server-sumarsono.com-3.png" alt="Glue Record Porkbun" /></p>
<p>Setelah semua beres, tinggal langkah terakhir. NS di porkbun ganti menjadi</p>
<table><thead><tr><th>NS Awal</th><th>NS Akhir</th></tr></thead><tbody>
<tr><td>ns1.he.net</td><td>ns1.sumarsono.com</td></tr>
<tr><td>ns2.he.net</td><td>ns2.sumarsono.com</td></tr>
<tr><td>ns3.he.net</td><td>ns3.sumarsono.com</td></tr>
<tr><td>ns4.he.net</td><td>ns4.sumarsono.com</td></tr>
<tr><td>ns5.he.net</td><td>ns5.sumarsono.com</td></tr>
</tbody></table>
<p>Setelah propagasi selesai, kita bisa cek NS kita</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">drill NS sumarsono.com
</span><span>
</span><span style="font-style:italic;color:#928374;"># output
</span><span>;</span><span style="color:#b23c15;">; </span><span style="color:#282828;">-</span><span style="color:#b23c15;">>></span><span style="color:#282828;">HEADER</span><span style="color:#b23c15;"><<- </span><span style="color:#9d0006;">opcode</span><span style="color:#282828;">: QUERY, rcode: NOERROR, id: 28941
</span><span style="color:#282828;">;; flags: qr rd ra ; QUERY: 1, ANSWER: 5, AUTHORITY: 0, ADDITIONAL: 0
</span><span style="color:#282828;">;; QUESTION SECTION:
</span><span style="color:#282828;">;; sumarsono.com. IN NS
</span><span style="color:#282828;">
</span><span style="color:#282828;">;; ANSWER SECTION:
</span><span style="color:#282828;">sumarsono.com. 28515 IN NS ns5.sumarsono.com.
</span><span style="color:#282828;">sumarsono.com. 28515 IN NS ns3.sumarsono.com.
</span><span style="color:#282828;">sumarsono.com. 28515 IN NS ns2.sumarsono.com.
</span><span style="color:#282828;">sumarsono.com. 28515 IN NS ns4.sumarsono.com.
</span><span style="color:#282828;">sumarsono.com. 28515 IN NS ns1.sumarsono.com.
</span><span style="color:#282828;">
</span><span style="color:#282828;">;; AUTHORITY SECTION:
</span><span style="color:#282828;">
</span><span style="color:#282828;">;; ADDITIONAL SECTION:
</span><span style="color:#282828;">
</span><span style="color:#282828;">;; Query time: 103 msec
</span><span style="color:#282828;">;; SERVER: 9.9.9.9
</span><span style="color:#282828;">;; WHEN: Fri Sep 25 16:36:11 2020
</span><span style="color:#282828;">;; MSG SIZE rcvd: 121
</span></code></pre>
<p>Cek pakai Whois</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">whois sumarsono.com
</span></code></pre>
<p>Hasilnya</p>
<p><img src="https://sumarsimages.files.wordpress.com/2020/09/vanity-name-server-sumarsono.com_.png" alt="whois sumarsono.com" /></p>
<p>Cool~</p>
Lxd Manjaro
2020-09-24T09:34:55+07:00
2020-09-24T09:34:55+07:00
Unknown
https://www.sumarsono.com/lxd-manjaro/
<p>LXD is a container and virtual-machine "hypervisor" and a new user experience for Linux Containers. Ya sepemahaman bodohku sih lxd ini frontend buat LXC.
Install lxd di Manjaro juga gampang banget, tinggal install lewat pacman.</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">sudo pacman -S lxc lxd
</span><span style="color:#282828;">sudo systemctl enable --now lxc lxd
</span></code></pre>
<p>Masalahnya adalah ketika aku coba bikin satu kontainer Debian 10 64bit.</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">lxc launch images:debian/10/amd64 debian
</span></code></pre>
<p>Muncul error:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">Creating debian
</span><span style="color:#282828;">Starting debian
</span><span style="color:#282828;">Error: Failed to run: /usr/bin/lxd forkstart debian /var/lib/lxd/containers /var/log/lxd/debian/lxc.conf:
</span><span style="color:#282828;">Try `lxc info --show-log local:debian` for more info
</span></code></pre>
<p>Hmmm, baru mau mulai sudah error. Haha. Aku cek log sesuai petunjuk:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">lxc info --show-log local:debian
</span><span>
</span><span style="font-style:italic;color:#928374;"># outputnya
</span><span style="color:#282828;">Name: debian
</span><span style="color:#282828;">Location: none
</span><span style="color:#282828;">Remote: unix://
</span><span style="color:#282828;">Architecture: x86_64
</span><span style="color:#282828;">Created: 2020/09/24 02:08 UTC
</span><span style="color:#282828;">Status: Stopped
</span><span style="color:#282828;">Type: container
</span><span style="color:#282828;">Profiles: default
</span><span>
</span><span style="color:#282828;">Log:
</span><span>
</span><span style="color:#282828;">lxc debian 20200924020852.963 WARN cgfsng - cgroups/cgfsng.c:mkdir_eexist_on_last:1152 - File exists - Failed to create directory </span><span style="color:#79740e;">"/sys/fs/cgroup/cpuset//lxc.monitor.debian"
</span><span style="color:#282828;">lxc debian 20200924020852.964 WARN cgfsng - cgroups/cgfsng.c:mkdir_eexist_on_last:1152 - File exists - Failed to create directory </span><span style="color:#79740e;">"/sys/fs/cgroup/cpuset//lxc.payload.debian"
</span><span style="color:#282828;">lxc debian 20200924020852.971 ERROR conf - conf.c:lxc_map_ids:2817 - newuidmap failed to write mapping </span><span style="color:#79740e;">""</span><span style="color:#282828;">: newuidmap 2678 0 1000000 1000000000
</span><span style="color:#282828;">lxc debian 20200924020852.971 ERROR start - start.c:lxc_spawn:1732 - Failed to set up id mapping.
</span><span style="color:#282828;">lxc debian 20200924020852.971 ERROR lxccontainer - lxccontainer.c:wait_on_daemonized_start:849 - Received container state </span><span style="color:#79740e;">"ABORTING"</span><span style="color:#282828;"> instead of </span><span style="color:#79740e;">"RUNNING"
</span><span style="color:#282828;">lxc debian 20200924020852.972 ERROR start - start.c:__lxc_start:1999 - Failed to spawn container </span><span style="color:#79740e;">"debian"
</span><span style="color:#282828;">lxc debian 20200924020852.972 WARN start - start.c:lxc_abort:1018 - No such process - Failed to send SIGKILL via pidfd 30 for process 2678
</span><span style="color:#282828;">lxc debian 20200924020853.812 ERROR conf - conf.c:lxc_map_ids:2817 - newuidmap failed to write mapping </span><span style="color:#79740e;">""</span><span style="color:#282828;">: newuidmap 2696 1000000000 0 1 0 1000000 1000000000
</span><span style="color:#282828;">lxc debian 20200924020853.812 ERROR conf - conf.c:userns_exec_1:4023 - Error setting up {g,u}id mappings for child process </span><span style="color:#79740e;">"2696"
</span><span style="color:#282828;">lxc debian 20200924020853.818 WARN cgfsng - cgroups/cgfsng.c:cgfsng_payload_destroy:1048 - No such file or directory - Failed to destroy cgroups
</span><span style="color:#282828;">lxc debian 20200924020853.100 WARN cgfsng - cgroups/cgfsng.c:cgfsng_monitor_destroy:1109 - Success - Failed to initialize cpuset /sys/fs/cgroup/cpuset//lxc.pivot/lxc.pivot
</span><span style="color:#282828;">lxc 20200924020853.101 WARN commands - commands.c:lxc_cmd_rsp_recv:122 - Connection reset by peer - Failed to receive response for command </span><span style="color:#79740e;">"get_state"
</span></code></pre>
<p>Oh... error gara-gara gagal set uid+gid map. Lanjut cek, si container debian ini masu set uid berapa dan guid berapa.</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">sudo cat /var/log/lxd/debian/lxc.conf
</span><span>
</span><span style="font-style:italic;color:#928374;"># outputnya
</span><span style="color:#282828;">lxc.log.file = /var/log/lxd/debian/lxc.log
</span><span style="color:#282828;">lxc.log.level = warn
</span><span style="color:#282828;">lxc.console.buffer.size = auto
</span><span style="color:#282828;">lxc.console.size = auto
</span><span style="color:#282828;">lxc.console.logfile = /var/log/lxd/debian/console.log
</span><span style="color:#282828;">lxc.mount.auto = proc:rw sys:rw cgroup:mixed
</span><span style="color:#282828;">lxc.autodev = 1
</span><span style="color:#282828;">lxc.pty.max = 1024
</span><span style="color:#282828;">lxc.mount.entry = /dev/fuse dev/fuse none bind,create=file,optional 0 0
</span><span style="color:#282828;">lxc.mount.entry = /dev/net/tun dev/net/tun none bind,create=file,optional 0 0
</span><span style="color:#282828;">lxc.mount.entry = /proc/sys/fs/binfmt_misc proc/sys/fs/binfmt_misc none rbind,create=dir,optional 0 0
</span><span style="color:#282828;">lxc.mount.entry = /sys/firmware/efi/efivars sys/firmware/efi/efivars none rbind,create=dir,optional 0 0
</span><span style="color:#282828;">lxc.mount.entry = /sys/fs/fuse/connections sys/fs/fuse/connections none rbind,create=dir,optional 0 0
</span><span style="color:#282828;">lxc.mount.entry = /sys/fs/pstore sys/fs/pstore none rbind,create=dir,optional 0 0
</span><span style="color:#282828;">lxc.mount.entry = /sys/kernel/config sys/kernel/config none rbind,create=dir,optional 0 0
</span><span style="color:#282828;">lxc.mount.entry = /sys/kernel/debug sys/kernel/debug none rbind,create=dir,optional 0 0
</span><span style="color:#282828;">lxc.mount.entry = /sys/kernel/security sys/kernel/security none rbind,create=dir,optional 0 0
</span><span style="color:#282828;">lxc.mount.entry = /sys/kernel/tracing sys/kernel/tracing none rbind,create=dir,optional 0 0
</span><span style="color:#282828;">lxc.mount.entry = /dev/mqueue dev/mqueue none rbind,create=dir,optional 0 0
</span><span style="color:#282828;">lxc.include = /usr/share/lxc/config/common.conf.d/
</span><span style="color:#282828;">lxc.arch = linux64
</span><span style="color:#282828;">lxc.hook.version = 1
</span><span style="color:#282828;">lxc.hook.pre-start = /proc/4342/exe callhook /var/lib/lxd 2 start
</span><span style="color:#282828;">lxc.hook.stop = /usr/bin/lxd callhook /var/lib/lxd 2 stopns
</span><span style="color:#282828;">lxc.hook.post-stop = /usr/bin/lxd callhook /var/lib/lxd 2 stop
</span><span style="color:#282828;">lxc.tty.max = 0
</span><span style="color:#282828;">lxc.uts.name = debian
</span><span style="color:#282828;">lxc.mount.entry = /var/lib/lxd/devlxd dev/lxd none bind,create=dir 0 0
</span><span style="color:#282828;">lxc.apparmor.profile = lxd-debian_</span><span style="color:#b23c15;"><</span><span style="color:#282828;">/var/lib/lxd</span><span style="color:#b23c15;">></span><span style="color:#282828;">//</span><span style="color:#b23c15;">&</span><span style="color:#282828;">:lxd-debian_</span><span style="color:#b23c15;"><</span><span style="color:#282828;">var-lib-lxd</span><span style="color:#b23c15;">></span><span style="color:#282828;">:
</span><span style="color:#282828;">lxc.seccomp.profile = /var/lib/lxd/security/seccomp/debian
</span><span style="color:#282828;">lxc.idmap = u 0 1000000 1000000000
</span><span style="color:#282828;">lxc.idmap = g 0 1000000 1000000000
</span><span style="color:#282828;">lxc.mount.auto = shmounts:/var/lib/lxd/shmounts/debian:/dev/.lxd-mounts
</span><span style="color:#282828;">lxc.net.0.name = eth0
</span><span style="color:#282828;">lxc.net.0.type = phys
</span><span style="color:#282828;">lxc.net.0.flags = up
</span><span style="color:#282828;">lxc.net.0.link = vethf945f880
</span><span style="color:#282828;">lxc.rootfs.path = dir:/var/lib/lxd/containers/debian/rootfs
</span></code></pre>
<p>Yang aku butuhkan adalah baris:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>lxc.idmap = u 0 1000000 1000000000
</span><span>lxc.idmap = g 0 1000000 1000000000
</span></code></pre>
<p>Langsung saja aku set uid+gid map tersebut. Pertama aku set uid</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">sudo nano /etc/subuid
</span><span>
</span><span style="font-style:italic;color:#928374;"># isinya
</span><span style="color:#282828;">root:1000000:1000000000
</span><span style="color:#282828;">lxd:1000000:1000000000
</span></code></pre>
<p>Kedua gid map</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">sudo nano /etc/subgid
</span><span>
</span><span style="font-style:italic;color:#928374;"># isinya
</span><span style="color:#282828;">root:1000000:1000000000
</span><span style="color:#282828;">lxd:1000000:1000000000
</span></code></pre>
<p>Lanjut aku restart service lxc dan lxd</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">sudo systemctl restart lxc lxd
</span></code></pre>
<p>Cek daftar container</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">lxc list
</span><span>
</span><span style="font-style:italic;color:#928374;"># outputnya
</span><span style="color:#282828;">+--------+---------+------+------+-----------+-----------+
</span><span style="color:#b23c15;">| </span><span style="color:#282828;">NAME </span><span style="color:#b23c15;">| </span><span style="color:#282828;">STATE </span><span style="color:#b23c15;">| </span><span style="color:#282828;">IPV4 </span><span style="color:#b23c15;">| </span><span style="color:#282828;">IPV6 </span><span style="color:#b23c15;">| </span><span style="color:#282828;">TYPE </span><span style="color:#b23c15;">| </span><span style="color:#282828;">SNAPSHOTS </span><span style="color:#b23c15;">|
</span><span style="color:#282828;">+--------+---------+------+------+-----------+-----------+
</span><span style="color:#b23c15;">| </span><span style="color:#282828;">debian </span><span style="color:#b23c15;">| </span><span style="color:#282828;">STOPPED </span><span style="color:#b23c15;">| | | </span><span style="color:#282828;">CONTAINER </span><span style="color:#b23c15;">| </span><span style="color:#282828;">0 </span><span style="color:#b23c15;">|
</span><span style="color:#282828;">+--------+---------+------+------+-----------+-----------+
</span></code></pre>
<p>Start container tersebut</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">lxc start debian
</span><span style="color:#282828;">lxc list
</span><span>
</span><span style="font-style:italic;color:#928374;"># outputnya
</span><span style="color:#282828;">+--------+---------+----------------------+-----------------------------------------------+-----------+-----------+
</span><span style="color:#b23c15;">| </span><span style="color:#282828;">NAME </span><span style="color:#b23c15;">| </span><span style="color:#282828;">STATE </span><span style="color:#b23c15;">| </span><span style="color:#282828;">IPV4 </span><span style="color:#b23c15;">| </span><span style="color:#282828;">IPV6 </span><span style="color:#b23c15;">| </span><span style="color:#282828;">TYPE </span><span style="color:#b23c15;">| </span><span style="color:#282828;">SNAPSHOTS </span><span style="color:#b23c15;">|
</span><span style="color:#282828;">+--------+---------+----------------------+-----------------------------------------------+-----------+-----------+
</span><span style="color:#b23c15;">| </span><span style="color:#282828;">debian </span><span style="color:#b23c15;">| </span><span style="color:#282828;">RUNNING </span><span style="color:#b23c15;">| </span><span style="color:#282828;">10.201.30.227 (eth0</span><span>) </span><span style="color:#b23c15;">| </span><span style="color:#282828;">fd42:678f:b042:ffc6:216:3eff:fe8d:3b14 (eth0</span><span>) </span><span style="color:#b23c15;">| </span><span style="color:#282828;">CONTAINER </span><span style="color:#b23c15;">| </span><span style="color:#282828;">0 </span><span style="color:#b23c15;">|
</span><span style="color:#282828;">+--------+---------+----------------------+-----------------------------------------------+-----------+-----------+
</span></code></pre>
<p>Cool~</p>
Tes Kirim Email Laravel via Artisan Tinker
2020-09-21T10:23:36+07:00
2020-09-21T10:23:36+07:00
Unknown
https://www.sumarsono.com/tes-kirim-email-laravel-via-artisan-tinker/
<p>Laravel bisa kirim email, konfigurasi smtp ada di dot env. Adakalanya aku edit dot env dan ingin segera tes dot env tersebut. Cara tercepat adalah tes lemat commnd line. Beruntung, laravel membawa artisan tinker.</p>
<p>Untuk kirim email laravel dari terminal/tinker, pertama edit .env dan isi konfigurasi smtp</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">MAIL_MAILER</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">smtp
</span><span style="color:#282828;">MAIL_HOST</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">striped-due-privacy.co.id
</span><span style="color:#282828;">MAIL_PORT</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">465
</span><span style="color:#282828;">MAIL_USERNAME</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">user@striped-due-privacy.co.id
</span><span style="color:#282828;">MAIL_PASSWORD</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">striped-due-privacy
</span><span style="color:#282828;">MAIL_ENCRYPTION</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">ssl
</span><span style="color:#282828;">MAIL_FROM_ADDRESS</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">user@striped-due-privacy.co.id
</span><span style="color:#282828;">MAIL_FROM_NAME</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">"${</span><span style="color:#282828;">APP_NAME</span><span style="color:#79740e;">}"
</span></code></pre>
<p>Clear config cache laravel</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">sudo -u www-data php artisan config:cache
</span></code></pre>
<p>Masuk ke tinker</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">sudo -u www-data php artisan tinker
</span></code></pre>
<p>Lalu jalankan script php</p>
<pre data-lang="php" style="background-color:#fcf0ca;color:#282828aa;" class="language-php "><code class="language-php" data-lang="php"><span>Mail::send('welcome', [], function($message) { $message->to('myawesomeemail@domain.com')->subject('Testing mails '); });
</span></code></pre>
<p>Selesai, langsung cek inbox myawesomeemail@domain.com, seharusnya sudah masuk, isinya html welcome blade yang sudah dirender. Kalau tidak masuk, maka akan ada error log dari tinker.</p>
<p>Cool~</p>
Debian 10 Bikin Email Alias Untuk Root
2020-09-20T17:36:41+07:00
2020-09-20T17:36:41+07:00
Unknown
https://www.sumarsono.com/debian-10-bikin-email-alias-untuk-root/
<p>System Operasi Debian 10 (server) kadang mengirim email ke user root. Email ini biasanya berisi notifikasi, misalnya notifikasi failed cron job, notifikasi failed auth, dan berbagai notifikasi sistem lainnya. Email notifikasi tersebut akan dikirim ke alamat root@hostname. Ya kalau kita login ke system sih kita bisa membaca email tersebut. Bagaimana kalau kita sedang sibuk engga sempat login ke system? Solusinya ya email tersebut dikirim ke email external. Cara untuk setup external email user debian 10 sangat mudah.</p>
<p>Pertama, edit <code>/etc/aliases</code>. Isi dari berkas tersebut sebelum aku edit adalah</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="font-style:italic;color:#928374;"># /etc/aliases
</span><span style="color:#282828;">mailer-daemon: postmaster
</span><span style="color:#282828;">postmaster: root
</span><span style="color:#282828;">nobody: root
</span><span style="color:#282828;">hostmaster: root
</span><span style="color:#282828;">usenet: root
</span><span style="color:#282828;">news: root
</span><span style="color:#282828;">webmaster: root
</span><span style="color:#282828;">www: root
</span><span style="color:#282828;">ftp: root
</span><span style="color:#282828;">abuse: root
</span><span style="color:#282828;">noc: root
</span><span style="color:#282828;">security: root
</span></code></pre>
<p>Aku hanya perlu menambahkan root: emailaku@domainaku.com, sehingga file <code>/etc/aliases</code> menjadi</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="font-style:italic;color:#928374;"># /etc/aliases
</span><span style="color:#282828;">mailer-daemon: postmaster
</span><span style="color:#282828;">postmaster: root
</span><span style="color:#282828;">nobody: root
</span><span style="color:#282828;">hostmaster: root
</span><span style="color:#282828;">usenet: root
</span><span style="color:#282828;">news: root
</span><span style="color:#282828;">webmaster: root
</span><span style="color:#282828;">www: root
</span><span style="color:#282828;">ftp: root
</span><span style="color:#282828;">abuse: root
</span><span style="color:#282828;">noc: root
</span><span style="color:#282828;">security: root
</span><span style="color:#282828;">root: emailku@domainku.com
</span></code></pre>
<p>Kedua, aku rebuild Sendmail's alias file.</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">newaliases
</span></code></pre>
<p>ketiga, test kirim email ke root</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#b57614;">echo </span><span style="color:#79740e;">"Notifikasi penggunaan server" </span><span style="color:#b23c15;">| </span><span style="color:#282828;">mail -s </span><span style="color:#79740e;">"Notifkasi Server"</span><span style="color:#282828;"> root
</span></code></pre>
<p>Hasilnya terlihat seperti gambar berikut
<img src="https://sumarsimages.files.wordpress.com/2020/09/email-to-root-debian-1.png" alt="Email to debian's root" /></p>
<p>Cool~</p>
Github Multiple Repositories Deploy Keys Dalam Satu Mesin
2020-09-17T08:11:04+07:00
2020-09-17T08:11:04+07:00
Unknown
https://www.sumarsono.com/github-multiple-repositories-deploy-keys-dalam-satu-mesin/
<p>Github mempunyai fitur Deploy Keys per repository, tempat untuk menaruh public key mesin supaya bisa pull/push tanpa password. Berbeda dengan fitur SSH and GPG Keys yang ada di Personal Setting, Deploy keys bisa spesifik per repository dan bisa diatur ijinnya apakah allow pull only atau allow pull+push. Deploy Keys dibuat untuk memudahkan proses CI/CD atau otomasi ketika deploy project.</p>
<p>Deploy Keys dapat diakses melalui Repo > Settings > Deploy Keys, cek gambar berikut:
<img src="https://sumarsimages.files.wordpress.com/2020/09/github-deploy-keys.png" alt="Github Deploy Keys" /></p>
<p>Permasalahannya adalah ketika kita hanya punya satu mesin, dan punya banyak repository, ketika kita memasukan public key yang sudah digunakan dalam repo lain, maka github akan komplain kalau key sudah digunakan. Untuk mengatasi hal ini, berikut ini caranya:</p>
<p>Sebagai contoh kasus, aku akan menambahkan Deploy Key untuk dua repo:</p>
<ul>
<li>git@github.com:nalakawula/lumens.git</li>
<li>git@github.com:nalakawula/fast-api.git
Pertama, Bikin ssh key pakai ssh-keygen sebanyak jumlah repo, masing-masing keypair disimpan dengan nama yang berbeda</li>
</ul>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">ssh-keygen -t ed25519 -f ~/.ssh/repo1 -C </span><span style="color:#79740e;">"mesin1"
</span><span style="color:#282828;">ssh-keygen -t ed25519 -f ~/.ssh/repo2 -C </span><span style="color:#79740e;">"mesin1"
</span></code></pre>
<p>Selanjutnya, tambahkan public key ke masing-masing repo</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">cat ~/.ssh/repo1.pub
</span><span style="color:#282828;">cat ~/.ssh/repo2.pub
</span></code></pre>
<p>Outputnya copas ke masing-masing deploy keys repo</p>
<p>Bikin ssh config ssh yang isinya</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">Host lumens github.com
</span><span> </span><span style="color:#282828;">Hostname github.com
</span><span> </span><span style="color:#282828;">IdentityFile /home/blackops/.ssh/repo1
</span><span style="color:#282828;">Host fast-api github.com
</span><span> </span><span style="color:#282828;">Hostname github.com
</span><span> </span><span style="color:#282828;">IdentityFile /home/blackops/.ssh/repo2
</span></code></pre>
<p>Terakhir tinggal pull reponya, tapi harus disesaikan</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">git pull git@github.com:nalakawula/lumens.git
</span></code></pre>
<p>Harus diubah menjadi</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">git pull git@lumens:nalakawula/lumens.git
</span></code></pre>
<p>Begitu juga untuk repo satunya lagi. Yes betul, yang diubah adalah hostnya.</p>
<p>Sekian dan terima gaji</p>
Cara Mudah Upgrade Ingress Controller Traefik V1 Ke V2 Tanpa Downtime
2020-09-09T20:58:05+07:00
2020-09-09T20:58:05+07:00
Unknown
https://www.sumarsono.com/cara-mudah-upgrade-ingress-controller-traefik-v1-ke-v2-tanpa-downtime/
<p>Traefik adalah reverse-proxy yang dibuat dalam konteks artikel ini yaitu reverse-proxy untuk service dalam kubernetes cluster. Dalam konteks artikel ini traefik berperan sebagai ingress controller. Tugasnya adalah untuk meneruskan request dari luar kubernetes cluster menuju service yang ada di dalam kubernetes cluster. Gambar berikut ini akan menjelaskan apa fungsi Traefik</p>
<p><img src="https://docs.traefik.io/assets/img/traefik-architecture.png" alt="Traefik" /></p>
<p>Traefik sebagai reverse proxy tentu saja belum sematang HAProxy atau Nginx. Lalu kenapa pakai traefik? karena Traefik sudah cukup stabil untuk habdle request, built-in let's encrypt integration, dan tentunya karena dukungan traefik sebagai kubernetes cluster ingress controller. Informasi lebih lanjut tentang traefik dapat di baca di <a href="https://docs.traefik.io/">halaman dokumentasi traefik</a>.</p>
<h2 id="upgrade-traefik">Upgrade Traefik</h2>
<p>Traefik yang baru lahir ini, tentu memiliki kekurangan. Salah satu kekurangan yang paling terasa adalah adanya major breaking changes ketika upgrade dari traefik v1.x ke traefik v2.x. Ingress object traefik v1 tidak bisa langsung dipakai oleh traefik v2, begitu juga dengan acme.json (Sertifikat let's encrypt) yang tidak kompatibel dengan traefik v2. Untuk acme.json, untungnya ada konverter yang disediakan, sehingga praktis memudahkan. Konverter acme.json traefik v1 ke traefik v2 bisa di cek di github <a href="https://github.com/containous/traefik-migration-tool">traefik-migration-tool</a>. Tinggal gunakan tool tersebut untuk konversi acme.json kemudian mount ke pvc yang akan digunakan traefik v2.</p>
<p>Untuk ingress object, ini yang masih PR. Harus manual konversinya. Masalah selanjutnya adalah bagaimana caranya split trafik antara traefik v1 dengan traefik v2. Split trafik ini untuk membagi trafik, trafik ingress object yang sudah dikonversi akan diarahkan ke traefik v2, sedangkan yang belum di konversi akan diarahkan ke traefik v1. Ya, migrasinya pelan-pelan, sambil melihat perkembangan hasil migrasi.</p>
<blockquote>
<p>"Anything that can go wrong will go wrong" -- Murphy's law</p>
</blockquote>
<p>Tulisan ini berisi sedikit effort yang aku tempuh untuk upgrade traefik v1 ke v2 tanpa downtime.</p>
<h2 id="topologi">Topologi</h2>
<p>Untungnya, ingress controller diciptakan dengan asumsi adanya load balancer di depan. Oleh sebab itu, sedari awal aku memasang HAproxy di depan kubernetes cluster. Dengan adanya HAproxy didepan kubernetes cluster, maka split trafik antara traefik v1 dengan trafik v2 menjadi mudah. Secara sederhana ada di gambar berikut ini:</p>
<p><img src="https://sumarsimages.files.wordpress.com/2020/09/topology-kubernetes-cluster-and-request-flow3.jpg" alt="Topologi" /></p>
<h2 id="deploy-traefik-v2">Deploy Traefik v2</h2>
<p>Selanjutnya, Deploy Traefik v2 ke dalam kubernetes cluster. Berkas yaml ini aku ambil dari dokumentasi traefik. Aku hanya melakukan beberapa penyesuaian sesuai kebutuhan, terutama untuk menerima proxy-protocol.</p>
<p>custom-resource.yaml traefik v2.x yang kupakai:</p>
<pre data-lang="yaml" style="background-color:#fcf0ca;color:#282828aa;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span style="font-weight:bold;color:#407959;">apiVersion</span><span>: </span><span style="color:#79740e;">apiextensions.k8s.io/v1beta1
</span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">CustomResourceDefinition
</span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">ingressroutes.traefik.containo.us
</span><span>
</span><span style="font-weight:bold;color:#407959;">spec</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">group</span><span>: </span><span style="color:#79740e;">traefik.containo.us
</span><span> </span><span style="font-weight:bold;color:#407959;">version</span><span>: </span><span style="color:#79740e;">v1alpha1
</span><span> </span><span style="font-weight:bold;color:#407959;">names</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">IngressRoute
</span><span> </span><span style="font-weight:bold;color:#407959;">plural</span><span>: </span><span style="color:#79740e;">ingressroutes
</span><span> </span><span style="font-weight:bold;color:#407959;">singular</span><span>: </span><span style="color:#79740e;">ingressroute
</span><span> </span><span style="font-weight:bold;color:#407959;">scope</span><span>: </span><span style="color:#79740e;">Namespaced
</span><span>
</span><span style="color:#407959;">---
</span><span style="font-weight:bold;color:#407959;">apiVersion</span><span>: </span><span style="color:#79740e;">apiextensions.k8s.io/v1beta1
</span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">CustomResourceDefinition
</span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">middlewares.traefik.containo.us
</span><span>
</span><span style="font-weight:bold;color:#407959;">spec</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">group</span><span>: </span><span style="color:#79740e;">traefik.containo.us
</span><span> </span><span style="font-weight:bold;color:#407959;">version</span><span>: </span><span style="color:#79740e;">v1alpha1
</span><span> </span><span style="font-weight:bold;color:#407959;">names</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">Middleware
</span><span> </span><span style="font-weight:bold;color:#407959;">plural</span><span>: </span><span style="color:#79740e;">middlewares
</span><span> </span><span style="font-weight:bold;color:#407959;">singular</span><span>: </span><span style="color:#79740e;">middleware
</span><span> </span><span style="font-weight:bold;color:#407959;">scope</span><span>: </span><span style="color:#79740e;">Namespaced
</span><span>
</span><span style="color:#407959;">---
</span><span style="font-weight:bold;color:#407959;">apiVersion</span><span>: </span><span style="color:#79740e;">apiextensions.k8s.io/v1beta1
</span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">CustomResourceDefinition
</span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">ingressroutetcps.traefik.containo.us
</span><span>
</span><span style="font-weight:bold;color:#407959;">spec</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">group</span><span>: </span><span style="color:#79740e;">traefik.containo.us
</span><span> </span><span style="font-weight:bold;color:#407959;">version</span><span>: </span><span style="color:#79740e;">v1alpha1
</span><span> </span><span style="font-weight:bold;color:#407959;">names</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">IngressRouteTCP
</span><span> </span><span style="font-weight:bold;color:#407959;">plural</span><span>: </span><span style="color:#79740e;">ingressroutetcps
</span><span> </span><span style="font-weight:bold;color:#407959;">singular</span><span>: </span><span style="color:#79740e;">ingressroutetcp
</span><span> </span><span style="font-weight:bold;color:#407959;">scope</span><span>: </span><span style="color:#79740e;">Namespaced
</span><span>
</span><span style="color:#407959;">---
</span><span style="font-weight:bold;color:#407959;">apiVersion</span><span>: </span><span style="color:#79740e;">apiextensions.k8s.io/v1beta1
</span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">CustomResourceDefinition
</span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">ingressrouteudps.traefik.containo.us
</span><span>
</span><span style="font-weight:bold;color:#407959;">spec</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">group</span><span>: </span><span style="color:#79740e;">traefik.containo.us
</span><span> </span><span style="font-weight:bold;color:#407959;">version</span><span>: </span><span style="color:#79740e;">v1alpha1
</span><span> </span><span style="font-weight:bold;color:#407959;">names</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">IngressRouteUDP
</span><span> </span><span style="font-weight:bold;color:#407959;">plural</span><span>: </span><span style="color:#79740e;">ingressrouteudps
</span><span> </span><span style="font-weight:bold;color:#407959;">singular</span><span>: </span><span style="color:#79740e;">ingressrouteudp
</span><span> </span><span style="font-weight:bold;color:#407959;">scope</span><span>: </span><span style="color:#79740e;">Namespaced
</span><span>
</span><span style="color:#407959;">---
</span><span style="font-weight:bold;color:#407959;">apiVersion</span><span>: </span><span style="color:#79740e;">apiextensions.k8s.io/v1beta1
</span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">CustomResourceDefinition
</span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">tlsoptions.traefik.containo.us
</span><span>
</span><span style="font-weight:bold;color:#407959;">spec</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">group</span><span>: </span><span style="color:#79740e;">traefik.containo.us
</span><span> </span><span style="font-weight:bold;color:#407959;">version</span><span>: </span><span style="color:#79740e;">v1alpha1
</span><span> </span><span style="font-weight:bold;color:#407959;">names</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">TLSOption
</span><span> </span><span style="font-weight:bold;color:#407959;">plural</span><span>: </span><span style="color:#79740e;">tlsoptions
</span><span> </span><span style="font-weight:bold;color:#407959;">singular</span><span>: </span><span style="color:#79740e;">tlsoption
</span><span> </span><span style="font-weight:bold;color:#407959;">scope</span><span>: </span><span style="color:#79740e;">Namespaced
</span><span>
</span><span style="color:#407959;">---
</span><span style="font-weight:bold;color:#407959;">apiVersion</span><span>: </span><span style="color:#79740e;">apiextensions.k8s.io/v1beta1
</span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">CustomResourceDefinition
</span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">tlsstores.traefik.containo.us
</span><span>
</span><span style="font-weight:bold;color:#407959;">spec</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">group</span><span>: </span><span style="color:#79740e;">traefik.containo.us
</span><span> </span><span style="font-weight:bold;color:#407959;">version</span><span>: </span><span style="color:#79740e;">v1alpha1
</span><span> </span><span style="font-weight:bold;color:#407959;">names</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">TLSStore
</span><span> </span><span style="font-weight:bold;color:#407959;">plural</span><span>: </span><span style="color:#79740e;">tlsstores
</span><span> </span><span style="font-weight:bold;color:#407959;">singular</span><span>: </span><span style="color:#79740e;">tlsstore
</span><span> </span><span style="font-weight:bold;color:#407959;">scope</span><span>: </span><span style="color:#79740e;">Namespaced
</span><span>
</span><span style="color:#407959;">---
</span><span style="font-weight:bold;color:#407959;">apiVersion</span><span>: </span><span style="color:#79740e;">apiextensions.k8s.io/v1beta1
</span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">CustomResourceDefinition
</span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">traefikservices.traefik.containo.us
</span><span>
</span><span style="font-weight:bold;color:#407959;">spec</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">group</span><span>: </span><span style="color:#79740e;">traefik.containo.us
</span><span> </span><span style="font-weight:bold;color:#407959;">version</span><span>: </span><span style="color:#79740e;">v1alpha1
</span><span> </span><span style="font-weight:bold;color:#407959;">names</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">TraefikService
</span><span> </span><span style="font-weight:bold;color:#407959;">plural</span><span>: </span><span style="color:#79740e;">traefikservices
</span><span> </span><span style="font-weight:bold;color:#407959;">singular</span><span>: </span><span style="color:#79740e;">traefikservice
</span><span> </span><span style="font-weight:bold;color:#407959;">scope</span><span>: </span><span style="color:#79740e;">Namespaced
</span><span>
</span><span style="color:#407959;">---
</span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">ClusterRole
</span><span style="font-weight:bold;color:#407959;">apiVersion</span><span>: </span><span style="color:#79740e;">rbac.authorization.k8s.io/v1beta1
</span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">traefik-ingress-controller
</span><span>
</span><span style="font-weight:bold;color:#407959;">rules</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">apiGroups</span><span>:
</span><span> - </span><span style="color:#79740e;">""
</span><span> </span><span style="font-weight:bold;color:#407959;">resources</span><span>:
</span><span> - </span><span style="color:#79740e;">services
</span><span> - </span><span style="color:#79740e;">endpoints
</span><span> - </span><span style="color:#79740e;">secrets
</span><span> </span><span style="font-weight:bold;color:#407959;">verbs</span><span>:
</span><span> - </span><span style="color:#79740e;">get
</span><span> - </span><span style="color:#79740e;">list
</span><span> - </span><span style="color:#79740e;">watch
</span><span> - </span><span style="font-weight:bold;color:#407959;">apiGroups</span><span>:
</span><span> - </span><span style="color:#79740e;">extensions
</span><span> </span><span style="font-weight:bold;color:#407959;">resources</span><span>:
</span><span> - </span><span style="color:#79740e;">ingresses
</span><span> </span><span style="font-weight:bold;color:#407959;">verbs</span><span>:
</span><span> - </span><span style="color:#79740e;">get
</span><span> - </span><span style="color:#79740e;">list
</span><span> - </span><span style="color:#79740e;">watch
</span><span> - </span><span style="font-weight:bold;color:#407959;">apiGroups</span><span>:
</span><span> - </span><span style="color:#79740e;">extensions
</span><span> </span><span style="font-weight:bold;color:#407959;">resources</span><span>:
</span><span> - </span><span style="color:#79740e;">ingresses/status
</span><span> </span><span style="font-weight:bold;color:#407959;">verbs</span><span>:
</span><span> - </span><span style="color:#79740e;">update
</span><span> - </span><span style="font-weight:bold;color:#407959;">apiGroups</span><span>:
</span><span> - </span><span style="color:#79740e;">traefik.containo.us
</span><span> </span><span style="font-weight:bold;color:#407959;">resources</span><span>:
</span><span> - </span><span style="color:#79740e;">middlewares
</span><span> - </span><span style="color:#79740e;">ingressroutes
</span><span> - </span><span style="color:#79740e;">traefikservices
</span><span> - </span><span style="color:#79740e;">ingressroutetcps
</span><span> - </span><span style="color:#79740e;">ingressrouteudps
</span><span> - </span><span style="color:#79740e;">tlsoptions
</span><span> - </span><span style="color:#79740e;">tlsstores
</span><span> </span><span style="font-weight:bold;color:#407959;">verbs</span><span>:
</span><span> - </span><span style="color:#79740e;">get
</span><span> - </span><span style="color:#79740e;">list
</span><span> - </span><span style="color:#79740e;">watch
</span><span>
</span><span style="color:#407959;">---
</span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">ClusterRoleBinding
</span><span style="font-weight:bold;color:#407959;">apiVersion</span><span>: </span><span style="color:#79740e;">rbac.authorization.k8s.io/v1beta1
</span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">traefik-ingress-controller
</span><span>
</span><span style="font-weight:bold;color:#407959;">roleRef</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">apiGroup</span><span>: </span><span style="color:#79740e;">rbac.authorization.k8s.io
</span><span> </span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">ClusterRole
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">traefik-ingress-controller
</span><span style="font-weight:bold;color:#407959;">subjects</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">ServiceAccount
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">traefik-ingress-controller
</span><span> </span><span style="font-weight:bold;color:#407959;">namespace</span><span>: </span><span style="color:#79740e;">traefikv2
</span></code></pre>
<p>deployment.yaml traefik v2.x yang kupakai:</p>
<pre data-lang="yaml" style="background-color:#fcf0ca;color:#282828aa;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span style="font-weight:bold;color:#407959;">apiVersion</span><span>: </span><span style="color:#79740e;">v1
</span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">ServiceAccount
</span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">namespace</span><span>: </span><span style="color:#79740e;">traefikv2
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">traefik-ingress-controller
</span><span>
</span><span style="color:#407959;">---
</span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">Deployment
</span><span style="font-weight:bold;color:#407959;">apiVersion</span><span>: </span><span style="color:#79740e;">apps/v1
</span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">namespace</span><span>: </span><span style="color:#79740e;">traefikv2
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">traefik
</span><span> </span><span style="font-weight:bold;color:#407959;">labels</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">app</span><span>: </span><span style="color:#79740e;">traefik
</span><span>
</span><span style="font-weight:bold;color:#407959;">spec</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">replicas</span><span>: </span><span style="color:#8f3f71;">1
</span><span> </span><span style="font-weight:bold;color:#407959;">selector</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">matchLabels</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">app</span><span>: </span><span style="color:#79740e;">traefik
</span><span> </span><span style="font-weight:bold;color:#407959;">template</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">labels</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">app</span><span>: </span><span style="color:#79740e;">traefik
</span><span> </span><span style="font-weight:bold;color:#407959;">spec</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">serviceAccountName</span><span>: </span><span style="color:#79740e;">traefik-ingress-controller
</span><span> </span><span style="font-weight:bold;color:#407959;">nodeSelector</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">kubernetes.io/hostname</span><span>: </span><span style="color:#79740e;">kubemaster
</span><span> </span><span style="font-weight:bold;color:#407959;">containers</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">traefik
</span><span> </span><span style="font-weight:bold;color:#407959;">image</span><span>: </span><span style="color:#79740e;">traefik:v2.2.11
</span><span> </span><span style="font-weight:bold;color:#407959;">args</span><span>:
</span><span> </span><span style="font-style:italic;color:#928374;">#- --api.insecure
</span><span> - </span><span style="color:#79740e;">--api=false
</span><span> - </span><span style="color:#79740e;">--accesslog=true
</span><span> - </span><span style="color:#79740e;">--accesslog.filepath=/mytraefik/access.log
</span><span> - </span><span style="color:#79740e;">--accesslog.bufferingsize=100
</span><span> - </span><span style="color:#79740e;">--log.level=INFO
</span><span> - </span><span style="color:#79740e;">--entrypoints.web.Address=:8000
</span><span> - </span><span style="color:#79740e;">--entryPoints.web.proxyProtocol.trustedIPs=192.168.140.66,192.168.140.67,192.168.140.68
</span><span> </span><span style="font-style:italic;color:#928374;">#- --entryPoints.web.proxyProtocol.insecure
</span><span> - </span><span style="color:#79740e;">--entrypoints.websecure.Address=:4443
</span><span> - </span><span style="color:#79740e;">--entryPoints.websecure.proxyProtocol.trustedIPs=192.168.140.66,192.168.140.67,192.168.140.68
</span><span> </span><span style="font-style:italic;color:#928374;">#- --entryPoints.websecure.proxyProtocol.insecure
</span><span> - </span><span style="color:#79740e;">--providers.kubernetescrd
</span><span> - </span><span style="color:#79740e;">--providers.kubernetescrd.ingressclass=traefik-dua
</span><span> - </span><span style="color:#79740e;">--certificatesresolvers.leprod.acme.tlschallenge
</span><span> - </span><span style="color:#79740e;">--certificatesresolvers.leprod.acme.email=sumarsono@mindosolutions.com
</span><span> - </span><span style="color:#79740e;">--certificatesresolvers.leprod.acme.storage=/mytraefik/acme-prod.json
</span><span> - </span><span style="color:#79740e;">--certificatesresolvers.lestaging.acme.tlschallenge
</span><span> - </span><span style="color:#79740e;">--certificatesresolvers.lestaging.acme.email=sumarsono@mindosolutions.com
</span><span> - </span><span style="color:#79740e;">--certificatesresolvers.lestaging.acme.storage=/mytraefik/acme-staging.json
</span><span> </span><span style="font-style:italic;color:#928374;"># Please note that this is the staging Let's Encrypt server.
</span><span> </span><span style="font-style:italic;color:#928374;"># Once you get things working, you should remove that whole line altogether.
</span><span> - </span><span style="color:#79740e;">--certificatesresolvers.lestaging.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory
</span><span> </span><span style="font-weight:bold;color:#407959;">ports</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">web
</span><span> </span><span style="font-weight:bold;color:#407959;">containerPort</span><span>: </span><span style="color:#8f3f71;">8000
</span><span> - </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">websecure
</span><span> </span><span style="font-weight:bold;color:#407959;">containerPort</span><span>: </span><span style="color:#8f3f71;">4443
</span><span> </span><span style="font-style:italic;color:#928374;">#- name: admin
</span><span> </span><span style="font-style:italic;color:#928374;"># containerPort: 8080
</span><span> </span><span style="font-weight:bold;color:#407959;">volumeMounts</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">traefikv2-persistent-storage
</span><span> </span><span style="font-weight:bold;color:#407959;">mountPath</span><span>: </span><span style="color:#79740e;">/mytraefik
</span><span> </span><span style="font-weight:bold;color:#407959;">volumes</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">traefikv2-persistent-storage
</span><span> </span><span style="font-weight:bold;color:#407959;">persistentVolumeClaim</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">claimName</span><span>: </span><span style="color:#79740e;">traefikv2-pvc
</span></code></pre>
<p>service.yaml traefik v2.x yang kupakai:</p>
<pre data-lang="yaml" style="background-color:#fcf0ca;color:#282828aa;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span style="font-weight:bold;color:#407959;">apiVersion</span><span>: </span><span style="color:#79740e;">v1
</span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">Service
</span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">traefik
</span><span> </span><span style="font-weight:bold;color:#407959;">namespace</span><span>: </span><span style="color:#79740e;">traefikv2
</span><span style="font-weight:bold;color:#407959;">spec</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">clusterIP</span><span>: </span><span style="color:#8f3f71;">10.99.235.116
</span><span> </span><span style="font-weight:bold;color:#407959;">ports</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">protocol</span><span>: </span><span style="color:#79740e;">TCP
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">web
</span><span> </span><span style="font-weight:bold;color:#407959;">port</span><span>: </span><span style="color:#8f3f71;">8000
</span><span> </span><span style="font-style:italic;color:#928374;">#- protocol: TCP
</span><span> </span><span style="font-style:italic;color:#928374;"># name: admin
</span><span> </span><span style="font-style:italic;color:#928374;"># port: 8080
</span><span> - </span><span style="font-weight:bold;color:#407959;">protocol</span><span>: </span><span style="color:#79740e;">TCP
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">websecure
</span><span> </span><span style="font-weight:bold;color:#407959;">port</span><span>: </span><span style="color:#8f3f71;">4443
</span><span> </span><span style="font-weight:bold;color:#407959;">selector</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">app</span><span>: </span><span style="color:#79740e;">traefik
</span></code></pre>
<p>middleware security-header traefik v2 yang kupakai:</p>
<pre data-lang="yaml" style="background-color:#fcf0ca;color:#282828aa;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span style="font-weight:bold;color:#407959;">apiVersion</span><span>: </span><span style="color:#79740e;">traefik.containo.us/v1alpha1
</span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">Middleware
</span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">security-header
</span><span style="font-weight:bold;color:#407959;">spec</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">headers</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">frameDeny</span><span>: </span><span style="color:#8f3f71;">true
</span><span> </span><span style="font-weight:bold;color:#407959;">sslRedirect</span><span>: </span><span style="color:#8f3f71;">true
</span><span> </span><span style="font-weight:bold;color:#407959;">browserXssFilter</span><span>: </span><span style="color:#8f3f71;">true
</span><span> </span><span style="font-weight:bold;color:#407959;">contentTypeNosniff</span><span>: </span><span style="color:#8f3f71;">true
</span><span> </span><span style="font-style:italic;color:#928374;">#HSTS
</span><span> </span><span style="font-weight:bold;color:#407959;">stsIncludeSubdomains</span><span>: </span><span style="color:#8f3f71;">true
</span><span> </span><span style="font-weight:bold;color:#407959;">stsPreload</span><span>: </span><span style="color:#8f3f71;">true
</span><span> </span><span style="font-weight:bold;color:#407959;">stsSeconds</span><span>: </span><span style="color:#8f3f71;">31536000
</span></code></pre>
<p>tls.options yang kupakai:</p>
<pre data-lang="yaml" style="background-color:#fcf0ca;color:#282828aa;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span style="font-weight:bold;color:#407959;">apiVersion</span><span>: </span><span style="color:#79740e;">traefik.containo.us/v1alpha1
</span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">TLSOption
</span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">mytlsoption
</span><span> </span><span style="font-weight:bold;color:#407959;">namespace</span><span>: </span><span style="color:#79740e;">default
</span><span style="font-weight:bold;color:#407959;">spec</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">minVersion</span><span>: </span><span style="color:#79740e;">VersionTLS12
</span><span> </span><span style="font-weight:bold;color:#407959;">cipherSuites</span><span>:
</span><span> - </span><span style="color:#79740e;">TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 </span><span style="font-style:italic;color:#928374;"># TLS 1.2
</span><span> - </span><span style="color:#79740e;">TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 </span><span style="font-style:italic;color:#928374;"># TLS 1.2
</span><span> - </span><span style="color:#79740e;">TLS_AES_256_GCM_SHA384 </span><span style="font-style:italic;color:#928374;"># TLS 1.3
</span><span> - </span><span style="color:#79740e;">TLS_CHACHA20_POLY1305_SHA256 </span><span style="font-style:italic;color:#928374;"># TLS 1.3
</span><span> </span><span style="font-weight:bold;color:#407959;">curvePreferences</span><span>:
</span><span> - </span><span style="color:#79740e;">CurveP521
</span><span> - </span><span style="color:#79740e;">CurveP384
</span><span> </span><span style="font-weight:bold;color:#407959;">sniStrict</span><span>: </span><span style="color:#8f3f71;">true
</span></code></pre>
<p>Hasil deploymentnya adalah sebagai berikut:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">NAME READY STATUS RESTARTS AGE
</span><span style="color:#282828;">pod/traefik-855559f97d-vm5vm 1/1 Running 0 10h
</span><span>
</span><span style="color:#282828;">NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S</span><span>) </span><span style="color:#282828;">AGE
</span><span style="color:#282828;">service/traefik ClusterIP 10.99.235.116 </span><span style="color:#b23c15;"><</span><span style="color:#282828;">none</span><span style="color:#b23c15;">> </span><span style="color:#8f3f71;">8000</span><span style="color:#282828;">/TCP,4443/TCP 51d
</span><span>
</span><span style="color:#282828;">NAME READY UP-TO-DATE AVAILABLE AGE
</span><span style="color:#282828;">deployment.apps/traefik 1/1 1 1 50d
</span></code></pre>
<h2 id="konfigurasi-haproxy">Konfigurasi HAproxy</h2>
<p>HAproxy harus dikonfigurasi dalam mode full passtrough, ssl di terminate di Traefik karena SSL manajemen akan dipegang oleh traefik. </p>
<p>Rule HAproxy secara singkat adalah sebagai berikut:</p>
<ul>
<li>Semua request HTTP redirect ke HTTPS</li>
<li>Semua request diarahkan ke Traefik v1 kecuali yang ada dalam ACL HAproxy</li>
<li>HAproxy send-proxy ke Traefik v1 karena traefik v1 tidak send-proxy-v2</li>
<li>HAproxy send-proxy-v2 ke Traefik v2</li>
</ul>
<p>Berikut ini adalah konfigurasi haproxy yang kupakai</p>
<p>bash
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
stats timeout 30s
user haproxy
group haproxy
daemon</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span> # Default SSL material locations
</span><span> ca-base /etc/ssl/certs
</span><span> crt-base /etc/ssl/private
</span><span>
</span><span> # Default ciphers to use on SSL-enabled listening sockets.
</span><span> # For more information, see ciphers(1SSL). This list is from:
</span><span> # https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
</span><span> # An alternative list with additional directives can be obtained from
</span><span> # https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=haproxy
</span><span> ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS
</span><span> ssl-default-bind-options no-sslv3
</span><span>
</span><span> nbproc 4
</span><span> cpu-map 1 1
</span><span> cpu-map 2 2
</span><span> cpu-map 3 3
</span><span> cpu-map 4 4
</span></code></pre>
<p>defaults
log global
mode http
option httplog
option dontlognull</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span> errorfile 400 /etc/haproxy/errors/400.http
</span><span> errorfile 403 /etc/haproxy/errors/403.http
</span><span> errorfile 408 /etc/haproxy/errors/408.http
</span><span> errorfile 500 /etc/haproxy/errors/500.http
</span><span> errorfile 502 /etc/haproxy/errors/502.http
</span><span> errorfile 503 /etc/haproxy/errors/503.http
</span><span> errorfile 504 /etc/haproxy/errors/504.http
</span><span>
</span><span>
</span><span> option redispatch
</span><span> retries 3
</span><span> timeout http-request 60s
</span><span> timeout queue 2m
</span><span> timeout connect 10s
</span><span> timeout client 2m
</span><span> timeout server 2m
</span><span> timeout http-keep-alive 60s
</span><span> timeout check 10s
</span><span> maxconn 3000
</span></code></pre>
<p>frontend http_front
bind *:80</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span> mode http
</span><span> http-request redirect scheme https code 301 if !{ ssl_fc }
</span></code></pre>
<p>frontend https_front
bind *:443
mode tcp
option tcplog</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span> tcp-request inspect-delay 5s
</span><span> tcp-request content capture req.ssl_sni len 25
</span><span>
</span><span> acl sumarsono_com req_ssl_sni -i sumarsono.com || req_ssl_sni -i www.sumarsono.com
</span><span>
</span><span> use_backend traefikv2_443 if sumarsono_com
</span><span>
</span><span> default_backend ingress_443
</span></code></pre>
<p>backend ingress_80
mode tcp
server traefik 127.0.0.1:30815 send-proxy maxconn 1000</p>
<p>backend ingress_443
mode tcp
server traefik 127.0.0.1:30814 send-proxy maxconn 1000</p>
<p>backend traefikv2_443
mode tcp
server traefikv2 10.99.235.116:4443 send-proxy-v2 maxconn 1000</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>
</span><span>
</span><span>
</span><span>## Migrasi Ingress Object Traefik v1 ke IngressRoutes Traefik v2
</span><span>
</span><span>Contoh ingress object traefik v1
</span><span>
</span><span>```yaml
</span><span>apiVersion: extensions/v1beta1
</span><span>kind: Ingress
</span><span>metadata:
</span><span> namespace: production
</span><span> name: sumarsono.com
</span><span> annotations:
</span><span> kubernetes.io/ingress.class: traefik
</span><span> ingress.kubernetes.io/browser-xss-filter: 'true'
</span><span> ingress.kubernetes.io/content-type-nosniff: 'true'
</span><span> traefik.ingress.kubernetes.io/redirect-permanent: "true"
</span><span> traefik.ingress.kubernetes.io/redirect-regex: ^https?://(www.)?(.*)
</span><span> traefik.ingress.kubernetes.io/redirect-replacement: https://${2}
</span><span> ingress.kubernetes.io/force-hsts: "true"
</span><span> ingress.kubernetes.io/hsts-max-age: "2592000"
</span><span> ingress.kubernetes.io/hsts-include-subdomains: "true"
</span><span> ingress.kubernetes.io/hsts-preload: "false"
</span><span> ingress.kubernetes.io/frame-deny: "true"
</span><span> ingress.kubernetes.io/custom-frame-options-value: "SAMEORIGIN"
</span><span> ingress.kubernetes.io/content-security-policy: upgrade-insecure-requests
</span><span>spec:
</span><span> rules:
</span><span> - host: sumarsono.com
</span><span> http:
</span><span> paths:
</span><span> - path: /
</span><span> backend:
</span><span> serviceName: apache
</span><span> servicePort: 80
</span><span> - host: www.sumarsono.com
</span><span> http:
</span><span> paths:
</span><span> - path: /
</span><span> backend:
</span><span> serviceName: apache
</span><span> servicePort: 80
</span></code></pre>
<p>Ingress object tersebut aku ubah menjadi IngressRoutes object traefik v2:</p>
<pre data-lang="yaml" style="background-color:#fcf0ca;color:#282828aa;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span style="font-weight:bold;color:#407959;">apiVersion</span><span>: </span><span style="color:#79740e;">traefik.containo.us/v1alpha1
</span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">IngressRoute
</span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">sumarsono.com
</span><span> </span><span style="font-weight:bold;color:#407959;">namespace</span><span>: </span><span style="color:#79740e;">production
</span><span> </span><span style="font-weight:bold;color:#407959;">annotations</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">kubernetes.io/ingress.class</span><span>: </span><span style="color:#79740e;">"traefik-dua"
</span><span style="font-weight:bold;color:#407959;">spec</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">entryPoints</span><span>:
</span><span> - </span><span style="color:#79740e;">web
</span><span> </span><span style="font-weight:bold;color:#407959;">routes</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">match</span><span>: </span><span style="color:#79740e;">"Host(`sumarsono.com`) || Host(`www.sumarsono.com`)"
</span><span> </span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">Rule
</span><span> </span><span style="font-weight:bold;color:#407959;">services</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">apache
</span><span> </span><span style="font-weight:bold;color:#407959;">port</span><span>: </span><span style="color:#8f3f71;">80
</span><span style="color:#407959;">---
</span><span style="font-weight:bold;color:#407959;">apiVersion</span><span>: </span><span style="color:#79740e;">traefik.containo.us/v1alpha1
</span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">IngressRoute
</span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">sumarsono.com-tls
</span><span> </span><span style="font-weight:bold;color:#407959;">namespace</span><span>: </span><span style="color:#79740e;">production
</span><span> </span><span style="font-weight:bold;color:#407959;">annotations</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">kubernetes.io/ingress.class</span><span>: </span><span style="color:#79740e;">"traefik-dua"
</span><span style="font-weight:bold;color:#407959;">spec</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">entryPoints</span><span>:
</span><span> - </span><span style="color:#79740e;">websecure
</span><span> </span><span style="font-weight:bold;color:#407959;">routes</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">match</span><span>: </span><span style="color:#79740e;">"Host(`sumarsono.com`) || Host(`www.sumarsono.com`)"
</span><span> </span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">Rule
</span><span> </span><span style="font-weight:bold;color:#407959;">services</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">production
</span><span> </span><span style="font-weight:bold;color:#407959;">port</span><span>: </span><span style="color:#8f3f71;">80
</span><span> </span><span style="font-weight:bold;color:#407959;">middlewares</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">security-header
</span><span> </span><span style="font-weight:bold;color:#407959;">namespace</span><span>: </span><span style="color:#79740e;">default
</span><span> </span><span style="font-weight:bold;color:#407959;">tls</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">certResolver</span><span>: </span><span style="color:#79740e;">leprod
</span><span> </span><span style="font-weight:bold;color:#407959;">options</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">mytlsoption
</span><span> </span><span style="font-weight:bold;color:#407959;">namespace</span><span>: </span><span style="color:#79740e;">default
</span></code></pre>
<p>Itulah ringkasan engga jelas dari effortku untuk upgrade traefik v1 ingress controller ke traefik v2 ingress controller tanpa downtime. Take with a grain of salt!</p>
Traefik V2 SSL A+ in Ssllabs
2020-09-03T13:59:06+07:00
2020-09-03T13:59:06+07:00
Unknown
https://www.sumarsono.com/traefik-v2-ssl-a-in-ssllabs/
<p>Untuk mendapatkan score a+ di SSL Labs ketika menggunakan traefik v2 sebagai ingress controller sangatlah mudah. Cukup membuat sebuah middleware dan sebuah TLSOption.</p>
<p>Pertama, buat sebuah middlewara object untuk traefik v2:</p>
<pre data-lang="yaml" style="background-color:#fcf0ca;color:#282828aa;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span style="font-weight:bold;color:#407959;">apiVersion</span><span>: </span><span style="color:#79740e;">traefik.containo.us/v1alpha1
</span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">Middleware
</span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">security-header
</span><span style="font-weight:bold;color:#407959;">spec</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">headers</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">frameDeny</span><span>: </span><span style="color:#8f3f71;">true
</span><span> </span><span style="font-weight:bold;color:#407959;">sslRedirect</span><span>: </span><span style="color:#8f3f71;">true
</span><span> </span><span style="font-weight:bold;color:#407959;">browserXssFilter</span><span>: </span><span style="color:#8f3f71;">true
</span><span> </span><span style="font-weight:bold;color:#407959;">contentTypeNosniff</span><span>: </span><span style="color:#8f3f71;">true
</span><span> </span><span style="font-style:italic;color:#928374;">#HSTS
</span><span> </span><span style="font-weight:bold;color:#407959;">stsIncludeSubdomains</span><span>: </span><span style="color:#8f3f71;">true
</span><span> </span><span style="font-weight:bold;color:#407959;">stsPreload</span><span>: </span><span style="color:#8f3f71;">true
</span><span> </span><span style="font-weight:bold;color:#407959;">stsSeconds</span><span>: </span><span style="color:#8f3f71;">31536000
</span></code></pre>
<p>Kemudian buat sebuah TLSOption</p>
<pre data-lang="yaml" style="background-color:#fcf0ca;color:#282828aa;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span style="font-weight:bold;color:#407959;">apiVersion</span><span>: </span><span style="color:#79740e;">traefik.containo.us/v1alpha1
</span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">TLSOption
</span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">mytlsoption
</span><span> </span><span style="font-weight:bold;color:#407959;">namespace</span><span>: </span><span style="color:#79740e;">default
</span><span style="font-weight:bold;color:#407959;">spec</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">minVersion</span><span>: </span><span style="color:#79740e;">VersionTLS12
</span><span> </span><span style="font-weight:bold;color:#407959;">cipherSuites</span><span>:
</span><span> - </span><span style="color:#79740e;">TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 </span><span style="font-style:italic;color:#928374;"># TLS 1.2
</span><span> - </span><span style="color:#79740e;">TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 </span><span style="font-style:italic;color:#928374;"># TLS 1.2
</span><span> - </span><span style="color:#79740e;">TLS_AES_256_GCM_SHA384 </span><span style="font-style:italic;color:#928374;"># TLS 1.3
</span><span> - </span><span style="color:#79740e;">TLS_CHACHA20_POLY1305_SHA256 </span><span style="font-style:italic;color:#928374;"># TLS 1.3
</span><span> </span><span style="font-weight:bold;color:#407959;">curvePreferences</span><span>:
</span><span> - </span><span style="color:#79740e;">CurveP521
</span><span> - </span><span style="color:#79740e;">CurveP384
</span><span> </span><span style="font-weight:bold;color:#407959;">sniStrict</span><span>: </span><span style="color:#8f3f71;">true
</span></code></pre>
<p>Apply kedua object diatas dengan kubectl.</p>
<p>Selanjutnya edit ingressRoutes traefik:</p>
<pre data-lang="yaml" style="background-color:#fcf0ca;color:#282828aa;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span style="font-weight:bold;color:#407959;">apiVersion</span><span>: </span><span style="color:#79740e;">traefik.containo.us/v1alpha1
</span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">IngressRoute
</span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">my.domain.co.id
</span><span> </span><span style="font-weight:bold;color:#407959;">namespace</span><span>: </span><span style="color:#79740e;">belajar
</span><span> </span><span style="font-weight:bold;color:#407959;">annotations</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">kubernetes.io/ingress.class</span><span>: </span><span style="color:#79740e;">"traefik-dua"
</span><span style="font-weight:bold;color:#407959;">spec</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">entryPoints</span><span>:
</span><span> - </span><span style="color:#79740e;">web
</span><span> </span><span style="font-weight:bold;color:#407959;">routes</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">match</span><span>: </span><span style="color:#79740e;">Host(`my.domain.co.id`)
</span><span> </span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">Rule
</span><span> </span><span style="font-weight:bold;color:#407959;">services</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">myapp-svc
</span><span> </span><span style="font-weight:bold;color:#407959;">port</span><span>: </span><span style="color:#8f3f71;">80
</span><span style="color:#407959;">---
</span><span style="font-weight:bold;color:#407959;">apiVersion</span><span>: </span><span style="color:#79740e;">traefik.containo.us/v1alpha1
</span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">IngressRoute
</span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">my.domain.co.id-tls
</span><span> </span><span style="font-weight:bold;color:#407959;">namespace</span><span>: </span><span style="color:#79740e;">belajar
</span><span> </span><span style="font-weight:bold;color:#407959;">annotations</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">kubernetes.io/ingress.class</span><span>: </span><span style="color:#79740e;">"traefik-dua"
</span><span style="font-weight:bold;color:#407959;">spec</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">entryPoints</span><span>:
</span><span> - </span><span style="color:#79740e;">websecure
</span><span> </span><span style="font-weight:bold;color:#407959;">routes</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">match</span><span>: </span><span style="color:#79740e;">Host(`my.domain.co.id`)
</span><span> </span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">Rule
</span><span> </span><span style="font-weight:bold;color:#407959;">services</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">myapp-svc
</span><span> </span><span style="font-weight:bold;color:#407959;">port</span><span>: </span><span style="color:#8f3f71;">80
</span><span> </span><span style="font-weight:bold;color:#407959;">middlewares</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">security-header
</span><span> </span><span style="font-weight:bold;color:#407959;">namespace</span><span>: </span><span style="color:#79740e;">default
</span><span> </span><span style="font-weight:bold;color:#407959;">tls</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">certResolver</span><span>: </span><span style="color:#79740e;">leprod
</span><span> </span><span style="font-weight:bold;color:#407959;">options</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">mytlsoption
</span><span> </span><span style="font-weight:bold;color:#407959;">namespace</span><span>: </span><span style="color:#79740e;">default
</span></code></pre>
<p>Perhatikan bagian spec.routes.middlewares.name dan spec.routes.middlewares.namespace pada object ingressRoutes my.domain.co.id-tls dan spec.tls.options.name dan spec.tls.options.namespace.
Itu adalah nama dari middleware dan tlsoption yang dibuat tadi. Namespace disesuaikan dengan lokasi dari middleware dan tlsoption.</p>
<p>Cek skor di SSL Labs, pasti A+.</p>
<p>Cool~</p>
Install TWRP Redmi 5 Plus Dari Manjaro Linux
2020-08-24T11:30:15+07:00
2020-08-24T11:30:15+07:00
Unknown
https://www.sumarsono.com/install-twrp-redmi-5-plus-dari-manjaro-linux/
<p>TWRP adalah Time Win Recovery, sebuah custom recovery untuk menggantikan recovery bawaan HP.
Cara install twrp untuk xiaomi redmi 5 plus umumnya menggunakan Windows. Oleh sebab itu aku tulis tutorial flash twrp redmi 5 plus dari linux, wabilkhusus dari Manjaro Linux. Intinya sih sama saja, untuk install TWRP redmi 5 plus kita butuh ADB tool dan fastboot tool. Kalau di Manjaro, adb dan fastboot ada dalam paket <a href="https://www.archlinux.org/packages/?name=android-tools">android-tools</a></p>
<p>Langsung saja, yang pertama tentu install android-tools</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">sudo pacman -S android-tools
</span></code></pre>
<p>Kemudian download TWRP redmi 5 plus dengan cara kunjungi <a href="https://dl.twrp.me/vince/">situs official TWRP untuk vince</a></p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">wget --header </span><span style="color:#79740e;">"Referer: https://dl.twrp.me"</span><span style="color:#282828;"> https://dl.twrp.me/vince/twrp-3.4.0-0-vince.img
</span></code></pre>
<p>Note: header referer diperlukan untuk download file img dari situs twrp</p>
<p>Terakhir install deh twrp redmi 5 plus, pastikan usb debug ON.</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">$ sudo adb devices
</span><span style="color:#282828;">$ adb reboot bootloader
</span><span style="color:#282828;">$ fastboot devices
</span><span style="color:#282828;">$ fastboot flash recovery twrp-3.4.0-0-vince.img
</span><span style="color:#282828;">$ fastboot boot twrp-3.4.0-0-vince.img
</span></code></pre>
<p>Selesai</p>
<p>Bonus: <a href="https://orangefox.download/en/device/vince">OrangFox</a>, custom TWRP dengan banyak fitur yang engga ada di official TWRP.</p>
Kubernetes Cluster Doomsday
2020-08-10T09:36:35+07:00
2020-08-10T09:36:35+07:00
Unknown
https://www.sumarsono.com/kubernetes-cluster-doomsday/
<p>Kubernetes has a ticking time bomb, that is the cluster's certificate. Kubernetes clusters work on top of TLS and rely on PKI certificates for authentication over TLS.</p>
<p>The Kubernetes cluster certificates have a lifespan of one year. If the Kubernetes cluster certificate expires on the Kubernetes master, then the <strong>kubelet</strong> service will fail. Issuing a <strong>kubectl</strong> command, such as <code>kubectl get pods</code> or <code>kubectl exec -it container_name bash</code>, will result in a message similar to Unable to connect to the server: x509: certificate has expired or is not yet valid.</p>
<p>I already know about that, and renew our cluster cert at <strong>Mar 16, 2020 04:20 UTC</strong></p>
<h2 id="a-nightmare-is-coming">A. Nightmare is coming</h2>
<p>But at 2020-08-09 18.26 (+0700) our cluster was down, every service was down. Try issuing <strong>kubectl</strong> command to check the cluster</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">$ kubectl get node -o wide
</span><span style="color:#282828;">Unable to connect to the server: x509: certificate has expired or is not yet valid
</span></code></pre>
<p>Check the kubelet log</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">$ sudo journalctl -fu kubelet
</span><span style="color:#282828;">août 09 13:46:38 KubeMaster kubelet</span><span style="color:#9d0006;">[</span><span style="color:#282828;">16214</span><span style="color:#9d0006;">]</span><span style="color:#282828;">: E0809 13:46:38.476674 16214 reflector.go:125] k8s.io/kubernetes/pkg/kubelet/config/apiserver.go:47: Failed to list </span><span style="color:#b23c15;">*</span><span style="color:#282828;">v1.Pod: Get https://192.168.140.66:6443/api/v1/pods</span><span style="color:#b23c15;">?</span><span style="color:#282828;">fieldSelector=spec.nodeName%</span><span style="color:#8f3f71;">3</span><span style="color:#282828;">Dkubemaster</span><span style="color:#b23c15;">&</span><span style="color:#282828;">limit</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">500&resourceVersion=0: </span><span style="color:#282828;">x509: certificate has expired or is not yet valid
</span><span style="color:#282828;">août 09 13:46:38 KubeMaster kubelet</span><span style="color:#9d0006;">[</span><span style="color:#282828;">16214</span><span style="color:#9d0006;">]</span><span style="color:#282828;">: E0809 13:46:38.532150 16214 kubelet.go:2248] node </span><span style="color:#79740e;">"kubemaster"</span><span style="color:#282828;"> not found
</span></code></pre>
<p>Hey..what happen, why our cluster certificates are expired, I already renew them on March 2020. Let's check our cluster certificates:</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">sumar@KubeMaster:~$ sudo kubeadm alpha certs check-expiration
</span><span style="color:#282828;">[sudo] Mot de passe de sumar :
</span><span style="color:#282828;">CERTIFICATE EXPIRES RESIDUAL TIME EXTERNALLY MANAGED
</span><span style="color:#282828;">admin.conf Mar 04, 2021 04:20 UTC 218d no
</span><span style="color:#282828;">apiserver Mar 04, 2021 04:20 UTC 218d no
</span><span style="color:#282828;">apiserver-etcd-client Mar 04, 2021 04:20 UTC 218d no
</span><span style="color:#282828;">apiserver-kubelet-client Mar 04, 2021 04:20 UTC 218d no
</span><span style="color:#282828;">controller-manager.conf Mar 04, 2021 04:20 UTC 218d no
</span><span style="color:#282828;">etcd-healthcheck-client Mar 04, 2021 04:20 UTC 218d no
</span><span style="color:#282828;">etcd-peer Mar 04, 2021 04:20 UTC 218d no
</span><span style="color:#282828;">etcd-server Mar 04, 2021 04:20 UTC 218d no
</span><span style="color:#282828;">front-proxy-client Mar 04, 2021 04:20 UTC 218d no
</span><span style="color:#282828;">scheduler.conf Mar 04, 2021 04:20 UTC 218d no
</span></code></pre>
<p>They are not expired yet. Shit, what happen.</p>
<h2 id="b-root-cause">B. Root cause</h2>
<p>Debugging kubernetes clusters is a pain in the ass. But at least I get what the real issue here. The root of all the problem is that the kubernetes api container does not pick our new cert. Hell yeah!</p>
<h2 id="c-wake-up-from-a-nightmare">C. Wake up from a nightmare</h2>
<p>The solution that save my ass:</p>
<ol>
<li>
<p>Regenerate all cluster Cert</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">$ kubeadm alpha certs renew all
</span><span style="color:#282828;">certificate embedded in the kubeconfig file for the admin to use and for kubeadm itself renewed
</span><span style="color:#282828;">certificate for serving the Kubernetes API renewed
</span><span style="color:#282828;">certificate the apiserver uses to access etcd renewed
</span><span style="color:#282828;">certificate for the API server to connect to kubelet renewed
</span><span style="color:#282828;">certificate embedded in the kubeconfig file for the controller manager to use renewed
</span><span style="color:#282828;">certificate for liveness probes to healtcheck etcd renewed
</span><span style="color:#282828;">certificate for etcd nodes to communicate with each other renewed
</span><span style="color:#282828;">certificate for serving etcd renewed
</span><span style="color:#282828;">certificate for the front proxy client renewed
</span><span style="color:#282828;">certificate embedded in the kubeconfig file for the scheduler manager to use renewed
</span></code></pre>
</li>
<li>
<p>Stop kubelet service of all nodes</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">$ sudo systemctl stop kubelet
</span></code></pre>
</li>
<li>
<p>Stop docker service of all nodes</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">$ sudo systemctl stop docker
</span></code></pre>
</li>
<li>
<p>Start docker service on master node</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">$ sudo systemctl start docker
</span></code></pre>
</li>
<li>
<p>Start kubelet service on master node</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">$ sudo systemctl start kubelet
</span></code></pre>
</li>
<li>
<p>Start docker service on every worker node</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">$ sudo systemctl start docker
</span></code></pre>
</li>
<li>
<p>Start kubelet service on every worker node</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">$ sudo systemctl start kubelet
</span></code></pre>
</li>
<li>
<p>Monitor kubelet log on all node</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">$ sudo journalctl -fu kubelet
</span></code></pre>
</li>
</ol>
<p>Why not use restart instead of shutdown? I try restart command but not work, kubelet still not pick new cert.</p>
<p>And now Wow, the log start back to normal state. All error log related to certificates is gone. But wait, not that fast. New error was coming, our calico pod was unable to start so every pod can not communicate each other. The solution is delete the pod, so kubernetes will recreate the calico pod.</p>
<p>Total downtime that caused by this issue is about 1 hour 10 minutes.</p>
Convert Putty Public Key to Openssh Public Key
2020-07-20T15:54:48+07:00
2020-07-20T15:54:48+07:00
Unknown
https://www.sumarsono.com/convert-putty-public-key-to-openssh-public-key/
<p>Aku jarang pakai putty, hehe. Di linux pakai terminal emulator udah cool dan gak perlu install. Tapi ada kalanya temen kita putty, dan ketika diminta untuk ngirim public key, sudah pasti dia akan generate pakai putty. Hal ini umum bagi pengguna OS Windows. Berbeda dengan pengguna OS linux yg pakai openSSh.</p>
<p>Format public key putty kira-kira begini:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>---- BEGIN SSH2 PUBLIC KEY ----
</span><span>Comment: "rsa-key-20200720"
</span><span>...
</span><span>key panjang disini>
</span><span>...
</span><span>---- END SSH2 PUBLIC KEY ----
</span></code></pre>
<p>Sedangkan public key openSSH:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>ssh-rsa ... key panjang disini ... sumar@sysadminPC
</span></code></pre>
<p>Kendala yang muncul adalah bagaimana cara kita memasukan public key putty ke dalam <code>authorized_keys</code> openSSH? Caranya adalah dengan cara konversi public key putty menjadi public key openssh. Caranya cukup sederhana dan mudah:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>ssh-keygen -i -f id_rsa_putty.pub > id_rsa.pub
</span></code></pre>
<p>Cool~</p>
Traefik V1 Ip Blocklist Part 2
2020-07-20T15:45:43+07:00
2020-07-20T15:45:43+07:00
Unknown
https://www.sumarsono.com/traefik-v1-ip-blocklist-part-2/
<p>Menyambung artikel tentang <a href="https://sumarsono.com/traefik-v1-ip-blocklist/">Traefik V1 Ip Blocklist</a>, ini sangat mudah karena tinggal setup forward auth doang. Kebetulan dulu aku install traefik v1.7.24 pakai Helm. Jadi untuk setup foward auth, aku tinggal edit <code>values.yaml</code>. Cukup edit/menambahkan</p>
<pre data-lang="yaml" style="background-color:#fcf0ca;color:#282828aa;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span style="font-weight:bold;color:#407959;">forwardAuth</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">entryPoints</span><span>: [</span><span style="color:#79740e;">"http"</span><span>, </span><span style="color:#79740e;">"https"</span><span>]
</span><span> </span><span style="font-weight:bold;color:#407959;">address</span><span>: </span><span style="color:#79740e;">http://ipfilter.fwdauth.svc.cluster.local/traefik
</span><span> </span><span style="font-weight:bold;color:#407959;">trustForwardHeader</span><span>: </span><span style="color:#8f3f71;">true
</span></code></pre>
<p>Note: <code>ipfilter.fwdauth.svc.cluster.local</code> ini mengikuti konvensi dns cluster k8s <code>nama-service.nama-namespace.svc.cluster.local</code></p>
<p>kemudian apply <code>values.yaml</code> dengan perintah <code>helm upgrade</code></p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">helm -n kube-system upgrade traefik stable/traefik -f 1.values.yaml
</span></code></pre>
<p>Selesai, sekarang traefik mendapatkan fungsi blocklist ip address.</p>
<p>Cool</p>
Traefik V1 Ip Blocklist
2020-07-17T15:25:56+07:00
2020-07-17T15:25:56+07:00
Unknown
https://www.sumarsono.com/traefik-v1-ip-blocklist/
<p>Traefik v1.7.24, ingress controller yang saat ini kupakai, tidak memiliki fitur blocklist IP Address tapi memilik fitur sebaliknya. Aneh ya. Umumnya blocklist dan allowlist ini satu paket. Sedikit konteks, aku pakai kubernetes. Ingress controller yang kupakai adalah traefik v1.7.24. Misal aku punya service chart-checkout. Aku ingin hanya IP address 140.213.59.224 yang boleh mengakses service tersebut, IP address lainnya harus di block, maka bisa pakai fitur bawaan traefik <del>whitelist</del> allowlist ip address. Masalahnya adalah ketika aku ingin service chart-checkout boleh diakses oleh semua IP address kecuali 140.213.59.224. Traefik gak punya fitur ip address blocklist. Sekali lagi, aneh. Btw konteks disini traefik v1.7.24 ya.</p>
<p>Disini harus memutar otak, untugnya traefik membawa fitur forwardAuth. Aku bisa memanfaatkan fitur traefik forwardAuth untuk blocklist ip address. Kira-kira begini alurnya:</p>
<ul>
<li>Request yang masuk ke traefik diteruskan ke auth server, jika ip address dalam request tersebut ada di blocklist maka kirim respon 403 dan request tidak diteruskan ke service chart-checkout.</li>
<li>Request yang masuk ke traefik diteruskan ke auth server, jika ip address dalam request tersebut tidak ada di blocklist maka kirim respon 200 dan request akan diteruskan ke service chart-checkout.</li>
</ul>
<p>Kira-kira begitu alur sederhananya. Langsung saja aku bikin auth servernya, dalam hal ini aku mau pakai nginx.</p>
<p>Pertama, aku bikin namespace untuk auth server:</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">kubectl create ns fwdauth
</span></code></pre>
<p>Kemudian aku siapkan dulu dua buah configmap untuk nginx yaitu <code>blocklist.yaml</code> dan <code>default.yaml</code>, di dalam blocklist aku mau block range ip <code>195.34.0.0/16</code></p>
<p>blocklist.yaml</p>
<pre data-lang="yaml" style="background-color:#fcf0ca;color:#282828aa;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span style="font-weight:bold;color:#407959;">apiVersion</span><span>: </span><span style="color:#79740e;">v1
</span><span style="font-weight:bold;color:#407959;">data</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">blocklist.conf</span><span>: </span><span style="color:#9d0006;">|
</span><span style="color:#79740e;"> # The following is a map of IP address/ranges with a value
</span><span style="color:#79740e;"> # that specifies if the IP address is allowed or not.
</span><span style="color:#79740e;"> # 0 = Allowed (default)
</span><span style="color:#79740e;"> # 1 = Denied (response 403) - any number above 0 will be considered as denied.
</span><span style="color:#79740e;"> geo $blocked_ip {
</span><span style="color:#79740e;"> default 0;
</span><span style="color:#79740e;">
</span><span style="color:#79740e;"> 195.34.0.0/16 1;
</span><span style="color:#79740e;"> #192.168.1.0/24 1;
</span><span style="color:#79740e;"> #10.1.0.0/16 1;
</span><span style="color:#79740e;"> }
</span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">ConfigMap
</span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">blocklist
</span><span> </span><span style="font-weight:bold;color:#407959;">namespace</span><span>: </span><span style="color:#79740e;">fwdauth
</span></code></pre>
<p>default.yaml</p>
<pre data-lang="yaml" style="background-color:#fcf0ca;color:#282828aa;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span style="font-weight:bold;color:#407959;">apiVersion</span><span>: </span><span style="color:#79740e;">v1
</span><span style="font-weight:bold;color:#407959;">data</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">default.conf</span><span>: </span><span style="color:#9d0006;">|
</span><span style="color:#79740e;"> server {
</span><span style="color:#79740e;"> listen 8080;
</span><span style="color:#79740e;"> location /traefik {
</span><span style="color:#79740e;"> add_header Content-Type "default_type text/plain";
</span><span style="color:#79740e;"> if ($blocked_ip) {
</span><span style="color:#79740e;"> return 403;
</span><span style="color:#79740e;"> }
</span><span style="color:#79740e;"> return 200 "OK";
</span><span style="color:#79740e;"> }
</span><span style="color:#79740e;"> }
</span><span style="color:#79740e;"> real_ip_header X-Forwarded-For;
</span><span style="color:#79740e;"> set_real_ip_from 0.0.0.0/0;
</span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">ConfigMap
</span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">nginx-default
</span><span> </span><span style="font-weight:bold;color:#407959;">namespace</span><span>: </span><span style="color:#79740e;">fwdauth
</span></code></pre>
<p>Note:</p>
<ul>
<li>real_ip_header diambil dari X-Forwarded-For karena Traefik ini dibelakang metallb</li>
<li>set_real_ip_from best practicenya cuma allow dari IP LB yang ada di depan traefik, aku allow semua krn masih test.</li>
</ul>
<p>Aku apply dua configmap tersebut:</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">kubectl apply -f default.yaml -f blocklist.yaml
</span></code></pre>
<p>Selanjutnya aku bikin deployment dan service ipfilter yg isinya nginx:</p>
<p>ipfilter.yaml</p>
<pre data-lang="yaml" style="background-color:#fcf0ca;color:#282828aa;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span style="font-weight:bold;color:#407959;">apiVersion</span><span>: </span><span style="color:#79740e;">v1
</span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">Service
</span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">namespace</span><span>: </span><span style="color:#79740e;">fwdauth
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">ipfilter
</span><span style="font-weight:bold;color:#407959;">spec</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">ports</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">port</span><span>: </span><span style="color:#8f3f71;">80
</span><span> </span><span style="font-weight:bold;color:#407959;">targetPort</span><span>: </span><span style="color:#8f3f71;">8080
</span><span> </span><span style="font-weight:bold;color:#407959;">selector</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">app</span><span>: </span><span style="color:#79740e;">ipfilter
</span><span style="color:#407959;">---
</span><span style="font-weight:bold;color:#407959;">apiVersion</span><span>: </span><span style="color:#79740e;">apps/v1
</span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">Deployment
</span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">namespace</span><span>: </span><span style="color:#79740e;">fwdauth
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">ipfilter
</span><span style="font-weight:bold;color:#407959;">spec</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">replicas</span><span>: </span><span style="color:#8f3f71;">3
</span><span> </span><span style="font-weight:bold;color:#407959;">selector</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">matchLabels</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">app</span><span>: </span><span style="color:#79740e;">ipfilter
</span><span> </span><span style="font-weight:bold;color:#407959;">strategy</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">type</span><span>: </span><span style="color:#79740e;">Recreate
</span><span> </span><span style="font-weight:bold;color:#407959;">template</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">labels</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">app</span><span>: </span><span style="color:#79740e;">ipfilter
</span><span> </span><span style="font-weight:bold;color:#407959;">spec</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">containers</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">image</span><span>: </span><span style="color:#79740e;">"nginx:1.14.2"
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">ipfilter
</span><span> </span><span style="font-weight:bold;color:#407959;">ports</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">containerPort</span><span>: </span><span style="color:#8f3f71;">8080
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">http
</span><span> </span><span style="font-weight:bold;color:#407959;">volumeMounts</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">nginx-default
</span><span> </span><span style="font-weight:bold;color:#407959;">mountPath</span><span>: </span><span style="color:#79740e;">/etc/nginx/conf.d/default.conf
</span><span> </span><span style="font-weight:bold;color:#407959;">subPath</span><span>: </span><span style="color:#79740e;">default.conf
</span><span> - </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">blocklist
</span><span> </span><span style="font-weight:bold;color:#407959;">mountPath</span><span>: </span><span style="color:#79740e;">/etc/nginx/conf.d/blocklist.conf
</span><span> </span><span style="font-weight:bold;color:#407959;">subPath</span><span>: </span><span style="color:#79740e;">blocklist.conf
</span><span> </span><span style="font-weight:bold;color:#407959;">volumes</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">blocklist
</span><span> </span><span style="font-weight:bold;color:#407959;">configMap</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">blocklist
</span><span> - </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">nginx-default
</span><span> </span><span style="font-weight:bold;color:#407959;">configMap</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">nginx-default
</span></code></pre>
<p>Untuk test sangat mudah, aku tinggal exec ke salah satu pod yg punya cUrl kemudian jalankan:</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">curl -iL -H </span><span style="color:#79740e;">"X-Forwarded-For: 195.34.243.179"</span><span style="color:#282828;"> ipfilter.fwdauth.svc.cluster.local/traefik
</span><span style="color:#282828;">HTTP/1.1 403 Forbidden
</span><span style="color:#282828;">Server: nginx/1.14.2
</span><span style="color:#282828;">Date: Fri, 17 Jul 2020 08:09:09 GMT
</span><span style="color:#282828;">Content-Type: text/html
</span><span style="color:#282828;">Content-Length: 169
</span><span style="color:#282828;">Connection: keep-alive
</span><span>
</span><span style="color:#b23c15;"><</span><span>html</span><span style="color:#b23c15;">>
</span><span style="color:#b23c15;"><</span><span>head</span><span style="color:#b23c15;">><</span><span>title</span><span style="color:#b23c15;">></span><span style="color:#8f3f71;">403 </span><span style="color:#282828;">Forbidden</span><span style="color:#b23c15;"><</span><span style="color:#282828;">/title</span><span style="color:#b23c15;">><</span><span style="color:#282828;">/head</span><span style="color:#b23c15;">>
</span><span style="color:#b23c15;"><</span><span>body </span><span style="color:#282828;">bgcolor</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">"white"</span><span style="color:#b23c15;">>
</span><span style="color:#b23c15;"><</span><span>center</span><span style="color:#b23c15;">><</span><span>h1</span><span style="color:#b23c15;">></span><span style="color:#8f3f71;">403 </span><span style="color:#282828;">Forbidden</span><span style="color:#b23c15;"><</span><span style="color:#282828;">/h1</span><span style="color:#b23c15;">><</span><span style="color:#282828;">/center</span><span style="color:#b23c15;">>
</span><span style="color:#b23c15;"><</span><span>hr</span><span style="color:#b23c15;">><</span><span>center</span><span style="color:#b23c15;">></span><span>nginx/1.14.2</span><span style="color:#b23c15;"><</span><span>/center</span><span style="color:#b23c15;">>
</span><span style="color:#b23c15;"><</span><span>/body</span><span style="color:#b23c15;">>
</span><span style="color:#b23c15;"><</span><span>/html</span><span style="color:#b23c15;">>
</span></code></pre>
<p>IP <code>195.34.243.179</code> masuk dalam range <code>195.34.0.0/16</code> yang ada di blocklist. Sesuai harapan dia di block.</p>
<p>Lanjut,</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">curl -iL ipfilter.fwdauth.svc.cluster.local/traefik
</span><span style="color:#282828;">HTTP/1.1 200 OK
</span><span style="color:#282828;">Server: nginx/1.14.2
</span><span style="color:#282828;">Date: Fri, 17 Jul 2020 08:09:13 GMT
</span><span style="color:#282828;">Content-Type: application/octet-stream
</span><span style="color:#282828;">Content-Length: 2
</span><span style="color:#282828;">Connection: keep-alive
</span><span style="color:#282828;">Content-Type: default_type text/plain
</span><span>
</span><span style="color:#282828;">OK
</span></code></pre>
<p>Selain ip dalam range <code>195.34.0.0/16</code> responnya 200. Sesuai harapan.</p>
<p>Selanjutnya tinggal konfigurasi forwardAuth di Traefik, tapi aku lanjutkan kapan-kapan, sementara sampai disini dulu</p>
<p>bersambung~~</p>
<p><a href="https://sumarsono.com/traefik-v1-ip-blocklist-part-2">Traefik V1 Ip Blocklist Part 2</a></p>
Msmtp Debian 10
2020-07-02T11:45:50+07:00
2020-07-02T11:45:50+07:00
Unknown
https://www.sumarsono.com/msmtp-debian-10/
<p>Aku pengen server Debian 10 punyaku bisa kirim email pakai external smtp server. Ada banyak caranya, kali ini aku mau pakai msmtp.</p>
<p>Pertama, aku install paket msmtp, dan bsd-mailx (yg ini supaya kita bisa pakai command <code>mail</code>)</p>
<p>bash
apt install msmtp msmtp-mta bsd-mailx</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>
</span><span>Terus, aku bikin konfigurasi msmtp
</span><span>
</span><span>bash
</span><span>nano ~/.msmtprc
</span></code></pre>
<p>Isi dari <code>~/.msmtprc</code>:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>defaults
</span><span>port 587
</span><span>tls on
</span><span>tls_trust_file /etc/ssl/certs/ca-certificates.crt
</span><span>auth on
</span><span>logfile ~/.msmtp.log
</span><span>
</span><span># akun smpt
</span><span>account nalakawula
</span><span>host smtp.domain.com
</span><span>port 587
</span><span>from user@domain.com
</span><span>user user@domain.com
</span><span>password password-email
</span><span>account default : nalakawula
</span></code></pre>
<p>Note: kalau pakai akun gmail, password-email diganti pakai app password.</p>
<p>Terakhir, tes kirim email:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>mail -s "Tes dari Server" user@domain-tujuan.com < /dev/null
</span></code></pre>
<p>Selesai</p>
Setup Bastion Host Pakai Haproxy Dan Wireguard
2020-07-01T11:01:36+07:00
2020-07-01T11:01:36+07:00
Unknown
https://www.sumarsono.com/setup-bastion-host-pakai-haproxy-dan-wireguard/
<h2 id="apa-itu-bastion-host">Apa itu Bastion host?</h2>
<p><strong>Bastion host</strong> adalah:</p>
<blockquote>
<p>A <strong>bastion host</strong> is a special-purpose computer on a network specifically designed and configured to withstand attacks. The computer generally hosts a single application, for example a <a href="https://en.wikipedia.org/wiki/Proxy_server">proxy server</a>, and all other services are removed or limited to reduce the threat to the computer. It is hardened in this manner primarily due to its location and purpose, which is either on the outside of a <a href="https://en.wikipedia.org/wiki/Firewall_(computing)">firewall</a> or in a demilitarized zone (<a href="https://en.wikipedia.org/wiki/Demilitarized_zone_(computing)">DMZ</a>) and usually involves access from untrusted networks or computers. -- <a href="https://en.wikipedia.org/wiki/Bastion_host">wikipedia</a></p>
</blockquote>
<h2 id="kenapa-aku-butuh-bastion-host">Kenapa aku butuh bastion host?</h2>
<p>Untuk meminimalkan pengeluaran uang. Haha. Jadi ceritanya begini:</p>
<p>Aku belajar banyak hal, dan hal-hal tersebut harus di hosting-kan. Contohnya, aku belajar kubernetes cluster dengan 3 node, masing-masing node memiliki spek 2 CPU dan 2 GB RAM. Kalau pakai cloud mahal dong tarifnya dengan spek segitu, 3 node pula. Solusi murah ya aku belajar di local, pakai VM (libvrit). PC local ini ada dibelakang NAT dan tidak boleh ada port forwarding dari router.</p>
<p>Bagaimana caranya aku expose service ke internet?. Misalnya aku deploy wordpress diatas kubernetes cluster, setup service wordpress, dan setup ingress untuk wordpress. Nah, kalau akses dari LAN mah gak msalah, kalau aku akses dari internet gimana? Ya pakai bastion host.</p>
<p>Aku butuh SSL dari lets encrypt, di local pc ada certbot, di kubernetes cluster ada cert-manage, bagaimana caranya aku menerima validasi dari Lets Encrypt kalau aku pilih challenge HTTP dan TLS/Alpn? Ya pakai bastion host.</p>
<h2 id="kok-bastion-host-dibilang-solusi-murah">Kok bastion host dibilang solusi murah?</h2>
<p>Murah karena aku cuma butuh spek kecil, cukup VPS dengan 1 CPU dan 512MB RAM. Harga sewa cuma 30rb rupiah. Aku sewa di <a href="https://www.virtua.host/vps-cloud-servers">virtua.host</a>. Bandingkan dengan harga sewa (2 CPU + 2 GB RAM) x 3 node.</p>
<h2 id="apa-yang-aku-perlukan-dari-bastion-host">Apa yang aku perlukan dari bastion host?</h2>
<ol>
<li>
<p>Aku butuh Wireguard</p>
<p><strong>Wireguard</strong> ini VPN tercepat yang pernah ku coba. Aku butuh VPN krn pc local ada di belakang NAT dan tidak boleh ada port forward dari router. Jadinya mau bikin koneksi peer to peer pakai wireguard.</p>
</li>
<li>
<p>Aku butuh HAProxy</p>
<p>HAProxy ini bertugas sebagia proxy dengan mode full passtrhough. Misal aku buka port 80 dan 443, maka incoming request akan diteruskan ke peer wireguard di PC local/VM. Mode full passtrough ini berfungsi supaya HAProxy tidak terminate SSL. Urursan SSL diserahkan ke belakang, alias di PC local/VM. Dengan begitu certbot atau cert-manager bisa berfungsi ketika memilih challenge HTTP atau TLS/ALPN.</p>
</li>
<li>
<p>Buang semua service di bastion host kecuali ssh, wireguard, dan HAProxy</p>
<p>Service yang ada di bastion host aku set seminimal mungkin, menyisakan ssh untuk remote shell, wireguard untuk vpn, dan HAProxy untuk proxy.</p>
</li>
<li>
<p>Firewall whitelist mode</p>
<p>Block semua kecuali yang diijinkan.</p>
</li>
</ol>
<h2 id="setup-wireguard">Setup Wireguard</h2>
<p>Instalasi silahkan ikuti dokumentasi mereka. Contoh konfigurasi wireguard yang kupakai:</p>
<p>bash
[Interface]
Address = 192.168.23.1/24
ListenPort = 51194
PrivateKey = isi-dengan-private-key-server</p>
<p>[Peer]
PublicKey = isi-dengan-pubkey-peer
PresharedKey = samakan-preshared-key-dengan-peer
AllowedIPs = 192.168.23.2/32, 192.168.100.0/24</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>
</span><span>Yang perlu diperhatikan adalah `AllowedIPs = 192.168.23.2/32, 192.168.100.0/24`:
</span><span>
</span><span>- 192.168.23.2/32 adalah ip address peer
</span><span>- 192.168.100.0/24 adalah ip address ingress yang dimasukin ke metallb layer2. Tujuan dari memasukan ini adalah supaya bastion host bisa komunikasi dengan ingress di kubernetes cluster. Dengan begini haproxy bisa komunikasi langsung ke ingress yang ada di kubernetes cluster.
</span><span>
</span><span>## Setup HAProxy
</span><span>
</span><span>Install aja sesuai dokumentasi mereka. Contoh konfigurasi yang kupaka:
</span><span>
</span></code></pre>
<p>global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
stats timeout 30s
user haproxy
group haproxy
daemon</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span># Default SSL material locations
</span><span>#ca-base /etc/ssl/certs
</span><span>#crt-base /etc/ssl/private
</span><span>
</span><span>#ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS
</span><span>#ssl-default-bind-options no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets
</span><span>#tune.ssl.cachesize 500000
</span></code></pre>
<p>defaults
mode http
log global
option redispatch
retries 3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>errorfile 400 /etc/haproxy/errors-custom/400.http
</span><span>errorfile 403 /etc/haproxy/errors-custom/403.http
</span><span>errorfile 408 /etc/haproxy/errors-custom/408.http
</span><span>errorfile 500 /etc/haproxy/errors-custom/500.http
</span><span>errorfile 502 /etc/haproxy/errors-custom/502.http
</span><span>errorfile 503 /etc/haproxy/errors-custom/503.http
</span><span>errorfile 504 /etc/haproxy/errors-custom/504.http
</span></code></pre>
<p>frontend http_front
bind 185.10.17.182:80
mode tcp
option tcplog
default_backend ingress_80</p>
<p>frontend https_front
bind 185.10.17.182:443
mode tcp
option tcplog
default_backend ingress_443</p>
<p>backend ingress_80
mode tcp
server server1 192.168.100.30:80 check send-proxy-v2</p>
<p>backend ingress_443
mode tcp
server server1 192.168.100.30:443 check send-proxy-v2</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>
</span><span>Disini haproxy mode full passtrough dan di set untuk kirim data send-proxy-v2, kubernetes ingress harus di set untuk accept proxy, kebetulan disini pakai nginx ingress controller, jadi edit configmap nya dan tambahkan:
</span><span>
</span><span>```yaml
</span><span>apiVersion: v1
</span><span>kind: ConfigMap
</span><span>data:
</span><span> proxy-real-ip-cidr: 192.168.100.0/24, 192.168.23.0/24
</span><span> use-proxy-protocol: "true"
</span><span> use-forwarded-headers: "true"
</span><span> compute-full-forwarded-for: "true"
</span><span>...
</span><span>...
</span></code></pre>
<p>Inti dari semua hal diatas adalah meneruskan incoming request ke VM local lewat wireguard:</p>
<p>bash
Internet -> Haproxy -> wiregurad -> VM lokal</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>
</span></code></pre>
Install K3s Tanpa Traefik Dan Servielb
2020-06-29T13:19:35+07:00
2020-06-29T13:19:35+07:00
Unknown
https://www.sumarsono.com/install-k3s-tanpa-traefik-dan-servielb/
<p>Sekilas tentang K3S yang ku kutip dari <a href="https://rancher.com/docs/k3s/latest/en/">dokumentasi k3s</a>:</p>
<p>K3s is a fully compliant Kubernetes distribution with the following enhancements:</p>
<ul>
<li>Packaged as a single binary.</li>
<li>Lightweight storage backend based on sqlite3 as the default storage mechanism. etcd3, MySQL, Postgres also still available.</li>
<li>Wrapped in simple launcher that handles a lot of the complexity of TLS and options.</li>
<li>Secure by default with reasonable defaults for lightweight environments.</li>
<li>Simple but powerful “batteries-included” features have been added, such as: a local storage provider, a service load balancer, a Helm controller, and the Traefik ingress controller.</li>
<li>Operation of all Kubernetes control plane components is encapsulated in a single binary and process. This allows K3s to automate and manage complex cluster operations like distributing certificates.</li>
<li>External dependencies have been minimized (just a modern kernel and cgroup mounts needed). K3s packages required dependencies, including:
<ul>
<li>containerd</li>
<li>Flannel</li>
<li>CoreDNS</li>
<li>CNI</li>
<li>Host utilities (iptables, socat, etc)</li>
<li>Ingress controller (traefik)</li>
<li>Embedded service loadbalancer</li>
<li>Embedded network policy controller</li>
</ul>
</li>
</ul>
<p>Jadi yang aku tangkap ya k3s ini versi mini k8s, banyak komponen k8s yang di strip. Waktu pertama kali nyobain k3s, dia langsung bawa ServiceLB buat assign IP addr ke service bertype LoadBalancer. Dan bawa traefik untuk ingress controller. Tapi kita bisa tinggalin dua itu kalau mau pakai yang lain, misalnya mau pakai Metallb sebagai pengganti Servicelb, dan pakai nginx sebagai pengganti Traefik. Caranya adalah sebagai berikut:</p>
<p>bash
$ export K3S_KUBECONFIG_MODE="644"
$ export INSTALL_K3S_EXEC=" --no-deploy servicelb --no-deploy traefik"
$ curl -sfL https://get.k3s.io | sh -</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>
</span><span>Dengan begitu traefik dan servicelb gak akan ikut diinstall. Selanjutnya tinggal install metallb dan nginx ingress controller dengan cara mengikuti dokumentasi masing-masing.
</span><span>
</span><span>cool~
</span></code></pre>
Kenapa Aku Pindah Dari Jekyll Ke Hugo
2020-06-29T12:55:34+07:00
2020-06-29T12:55:34+07:00
Unknown
https://www.sumarsono.com/kenapa-aku-pindah-dari-jekyll-ke-hugo/
<p>Aku sudah lama pakai SSG Jekyll, sejak tahun 2017. Jekyll ini sangat bagus, sebagai SSG dia udah cukup mature. Dukungan komunitas luas, dokumentasi oke dan mudah dipahami, theme yang bagus-bagus sudah bertebaran dimana-mana.</p>
<p>Tapi aku pindah ke Hugo, alasanku cuma satu sih yaitu Hugo cuma pakai single binary buat jalaninnya. Sedangkan Jekyll, dependesinya seabrek. Single binary dari hugo ini sangat memudahkan, gak perlu install apa-apa, modal download aja dari github release mereka dan run. Ketika aku pindah komputer, laptop, linux, windows, mac os, tinggal download satu binary aja. Sangat fleksibel, dibandingkan dengan jekyll. Cuma ini aja alasan kuat aku pindah dari jekyll ke Hugo.</p>
<p>Kenapa engga pindah ke hugo sejak dulu? karena awal-awal hugo naik ke permukaan, free theme dari komunitas sangat sedikit. Aku engga jago otak-atik html, css, dan js. Jadinya hanya bisa memakai theme yg sudah ada. Itu sebabnya bertahan di jekyll yang theme-nya sudah seabgrek.</p>
<p>Proses migrasi memakan waktu 1 hari. Migrasi konten jekyll ke hugo sangat cepat, tinggal ikutin <a href="https://gohugo.io/tools/migrations/#jekyll">panduan migrasi dari dokumentasi hugo</a>. Gak ada satu jam itu prosesnya, yang lama itu penyesuaian-penyesuaian. Aku pilih theme <a href="https://github.com/cntrump/hugo-notepadium">hugo-notepadium</a>, kemudian melakukan penyesuaian pada bagian-bagian yang aku engga sreg, misalnya menambah beberapa meta tag, mengganti ikon next dan previous, menambah i18n indonesia, dst.</p>
<p>Akhirnya migrasi dari jekyll ke hugo aku anggap selesai. Sisanya sambil jalan aja, soalnya masih baru juga pakai hugo, masih harus belajar lagi.</p>
<p>Cool~</p>
Setup Kubernetes Cluster Ubuntu 18.04 Pakai Kubeadm
2020-06-27T12:45:25+07:00
2020-06-27T12:45:25+07:00
Unknown
https://www.sumarsono.com/setup-kubernetes-cluster-ubuntu-18-04-pakai-kubeadmn/
<p>Ini adalah catatan bagaimana aku setup kubernetes cluster pakai kubeadm. Aku setup pakai VM (KVM) 1 master dan 1 node worker. Aku pakai vm ubuntu 18.04. Selama ini aku setup kubernetes cluster di debian 10. Sekarang belajar setup di ubuntu 18.04. Meskipun ubuntu berbasis debian, tapi ada beberapa yang berbeda ketika setup kubernetes cluster, yg paling kentara di Debian 10 adalah iptables-legacy.</p>
<p>Rangkuman singkatnya begini:</p>
<ul>
<li>install docker dan kubeadm di master</li>
<li>setup kubeadm di master</li>
<li>install docker dan kubeadm di node</li>
<li>join node ke cluster pakai kubeadm</li>
<li>Cluster selesai, sisanya pasang aplikasi sesua kebutuhan</li>
</ul>
<h1 id="log-install-kubernetes-di-ubuntu-18-04">Log install kubernetes di Ubuntu 18.04</h1>
<h1 id="a-setup-master">A. Setup Master</h1>
<ul>
<li>Node IP addr: 192.168.100.198</li>
<li>Node Hostname: master</li>
<li>OS: Ubuntu 18.04</li>
<li>RAM: 2 GB</li>
<li>CPU: 2 core</li>
</ul>
<h2 id="a-1-install-docker">A.1 Install docker</h2>
<p>Ikuti panduan https://docs.docker.com/engine/install/ubuntu/</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>apt-get update
</span><span>
</span><span>apt-get install \
</span><span> apt-transport-https \
</span><span> ca-certificates \
</span><span> curl \
</span><span> gnupg-agent \
</span><span> software-properties-common
</span></code></pre>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
</span></code></pre>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>add-apt-repository \
</span><span> "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
</span><span> $(lsb_release -cs) \
</span><span> stable"
</span></code></pre>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span> apt-get update
</span><span> apt-get install docker-ce docker-ce-cli containerd.io
</span></code></pre>
<h2 id="a-2-ganti-driver-docker-ke-systemd-awalnya-cgroupfs">A.2 Ganti driver docker ke systemd, awalnya cgroupfs</h2>
<p>bash</p>
<h1 id="set-up-the-docker-daemon">Set up the Docker daemon</h1>
<p>cat > /etc/docker/daemon.json <<EOF
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2"
}
EOF</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>
</span><span>bash
</span><span>mkdir -p /etc/systemd/system/docker.service.d
</span></code></pre>
<p>bash</p>
<h1 id="restart-docker">Restart Docker</h1>
<p>systemctl daemon-reload
systemctl restart docker
systemctl enable docker</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>
</span><span>## A.3 Install kubeadm
</span><span>
</span><span>Ikuti panduan https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/
</span><span>
</span><span>```bash
</span><span>cat <<EOF | tee /etc/sysctl.d/k8s.conf
</span><span>net.bridge.bridge-nf-call-ip6tables = 1
</span><span>net.bridge.bridge-nf-call-iptables = 1
</span><span>EOF
</span><span>sysctl --system
</span></code></pre>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">apt-get update </span><span style="color:#b23c15;">&& </span><span style="color:#282828;">apt-get install -y apt-transport-https curl
</span><span style="color:#282828;">curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg </span><span style="color:#b23c15;">| </span><span style="color:#282828;">apt-key add -
</span><span style="color:#282828;">cat </span><span style="color:#b23c15;"><<</span><span style="color:#9d0006;">EOF </span><span style="color:#b23c15;">| </span><span style="color:#282828;">tee /etc/apt/sources.list.d/kubernetes.list
</span><span style="color:#282828;">deb https://apt.kubernetes.io/ kubernetes-xenial main
</span><span style="color:#9d0006;">EOF
</span><span style="color:#282828;">apt-get update
</span><span style="color:#282828;">apt-get install -y kubelet kubeadm kubectl
</span><span style="color:#282828;">apt-mark hold kubelet kubeadm kubectl
</span></code></pre>
<h2 id="a-4-init-cluster-pakai-kubeadm">A.4 Init cluster pakai kubeadm</h2>
<p>Matikan swap</p>
<p>bash
swapoff -a</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>
</span><span>Matikan swap pas reboot pakai crontab
</span><span>
</span></code></pre>
<p>@reboot swapoff -a</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>
</span><span>
</span><span>
</span><span>Disini mau pakai flannel untuk networknya, oleh karena itu pakai parameter `--pod-network-cidr=10.244.0.0/16`
</span><span>
</span><span>bash
</span><span>kubeadm init --pod-network-cidr=10.244.0.0/16
</span></code></pre>
<p>bash
root@master:/home/sumar# kubectl get po -o wide -A
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kube-system coredns-66bff467f8-jghgf 0/1 Pending 0 4m22s <none> <none> <none> <none>
kube-system coredns-66bff467f8-zkcdd 0/1 Pending 0 4m22s <none> <none> <none> <none>
kube-system etcd-master 1/1 Running 0 4m32s 192.168.100.198 master <none> <none>
kube-system kube-apiserver-master 1/1 Running 0 4m32s 192.168.100.198 master <none> <none>
kube-system kube-controller-manager-master 1/1 Running 0 4m32s 192.168.100.198 master <none> <none>
kube-system kube-proxy-lc5ps 1/1 Running 0 4m22s 192.168.100.198 master <none> <none>
kube-system kube-scheduler-master 1/1 Running 0 4m32s 192.168.100.198 master <none> <none>
root@master:/home/sumar# </p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>
</span><span>pod coredns status pending krn belum install flannel,
</span><span>
</span><span>bash
</span><span>kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
</span></code></pre>
<p>Setelah install flannel, pod coredns jadi jalan</p>
<p>bash
root@master:/home/sumar# kubectl get po -o wide -A
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kube-system coredns-66bff467f8-jghgf 1/1 Running 0 8m19s 10.244.0.3 master <none> <none>
kube-system coredns-66bff467f8-zkcdd 1/1 Running 0 8m19s 10.244.0.2 master <none> <none>
kube-system etcd-master 1/1 Running 0 8m29s 192.168.100.198 master <none> <none>
kube-system kube-apiserver-master 1/1 Running 0 8m29s 192.168.100.198 master <none> <none>
kube-system kube-controller-manager-master 1/1 Running 0 8m29s 192.168.100.198 master <none> <none>
kube-system kube-flannel-ds-amd64-rb4wc 1/1 Running 0 46s 192.168.100.198 master <none> <none>
kube-system kube-proxy-lc5ps 1/1 Running 0 8m19s 192.168.100.198 master <none> <none>
kube-system kube-scheduler-master 1/1 Running 0 8m29s 192.168.100.198 master <none> <none></p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>
</span><span># B. Setup Nodesatu
</span><span>
</span><span>- Node IP addr: 192.168.100.199
</span><span>- Node Hostname: nodesatu
</span><span>- OS: Ubuntu 18.04
</span><span>- RAM: 2GB
</span><span>- CPU: 2 core
</span><span>
</span><span>## B.1 Install docker
</span><span>
</span><span>Ikuti panduan https://docs.docker.com/engine/install/ubuntu/
</span><span>
</span></code></pre>
<p>apt-get update</p>
<p>apt-get install <br />
apt-transport-https <br />
ca-certificates <br />
curl <br />
gnupg-agent <br />
software-properties-common</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>
</span></code></pre>
<p>curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>
</span></code></pre>
<p>add-apt-repository <br />
"deb [arch=amd64] https://download.docker.com/linux/ubuntu <br />
$(lsb_release -cs) <br />
stable"</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>
</span></code></pre>
<p>apt-get update
apt-get install docker-ce docker-ce-cli containerd.io</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>
</span><span>## B.2 Ganti driver docker ke systemd, awalnya cgroupfs
</span><span>
</span><span>bash
</span><span># Set up the Docker daemon
</span><span>cat > /etc/docker/daemon.json <<EOF
</span><span>{
</span><span> "exec-opts": ["native.cgroupdriver=systemd"],
</span><span> "log-driver": "json-file",
</span><span> "log-opts": {
</span><span> "max-size": "100m"
</span><span> },
</span><span> "storage-driver": "overlay2"
</span><span>}
</span><span>EOF
</span></code></pre>
<p>bash
mkdir -p /etc/systemd/system/docker.service.d</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>
</span><span>bash
</span><span># Restart Docker
</span><span>systemctl daemon-reload
</span><span>systemctl restart docker
</span><span>systemctl enable docker
</span></code></pre>
<h2 id="b-3-install-kubeadm">B.3 Install kubeadm</h2>
<p>Ikuti panduan https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">cat </span><span style="color:#b23c15;"><<</span><span style="color:#9d0006;">EOF </span><span style="color:#b23c15;">| </span><span style="color:#282828;">tee /etc/sysctl.d/k8s.conf
</span><span style="color:#282828;">net.bridge.bridge-nf-call-ip6tables = 1
</span><span style="color:#282828;">net.bridge.bridge-nf-call-iptables = 1
</span><span style="color:#9d0006;">EOF
</span><span style="color:#282828;">sysctl --system
</span></code></pre>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">apt-get update </span><span style="color:#b23c15;">&& </span><span style="color:#282828;">apt-get install -y apt-transport-https curl
</span><span style="color:#282828;">curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg </span><span style="color:#b23c15;">| </span><span style="color:#282828;">apt-key add -
</span><span style="color:#282828;">cat </span><span style="color:#b23c15;"><<</span><span style="color:#9d0006;">EOF </span><span style="color:#b23c15;">| </span><span style="color:#282828;">tee /etc/apt/sources.list.d/kubernetes.list
</span><span style="color:#282828;">deb https://apt.kubernetes.io/ kubernetes-xenial main
</span><span style="color:#9d0006;">EOF
</span><span style="color:#282828;">apt-get update
</span><span style="color:#282828;">apt-get install -y kubelet kubeadm kubectl
</span><span style="color:#282828;">apt-mark hold kubelet kubeadm kubectl
</span></code></pre>
<h2 id="b-4-join-nodesatu-ke-cluster">B.4 Join nodesatu ke cluster</h2>
<p>bash
kubeadm join 192.168.100.198:6443 --token 98vdpp.r7tziuipa5ebwpg8 <br />
--discovery-token-ca-cert-hash sha256:d6d44f1588470756cd52f70b5576aa7ddd6b5b9a57559b025dbfa21ecee2c0eb</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>
</span><span>
</span><span>
</span><span>Langkah A dan B adalah langkah untuk setup cluster. Setelah setup master selesai dan setup nodesatu selesai, kita verifikasi:
</span><span>
</span><span>bash
</span><span>root@master:~# kubectl cluster-info
</span><span>Kubernetes master is running at https://192.168.100.198:6443
</span><span>KubeDNS is running at https://192.168.100.198:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
</span><span>
</span><span>To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
</span><span>root@master:~# kubectl get nodes -o wide
</span><span>NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
</span><span>master Ready master 74m v1.18.5 192.168.100.198 <none> Ubuntu 18.04.4 LTS 4.15.0-108-generic docker://19.3.12
</span><span>nodesatu Ready <none> 41m v1.18.5 192.168.100.199 <none> Ubuntu 18.04.4 LTS 4.15.0-108-generic docker://19.3.12
</span><span>
</span><span>
</span><span>root@master:~# kubectl -n kube-system get po -o wide
</span><span>NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
</span><span>coredns-66bff467f8-jghgf 1/1 Running 0 77m 10.244.0.3 master <none> <none>
</span><span>coredns-66bff467f8-zkcdd 1/1 Running 0 77m 10.244.0.2 master <none> <none>
</span><span>etcd-master 1/1 Running 0 77m 192.168.100.198 master <none> <none>
</span><span>kube-apiserver-master 1/1 Running 0 77m 192.168.100.198 master <none> <none>
</span><span>kube-controller-manager-master 1/1 Running 0 77m 192.168.100.198 master <none> <none>
</span><span>kube-flannel-ds-amd64-rb4wc 1/1 Running 0 69m 192.168.100.198 master <none> <none>
</span><span>kube-flannel-ds-amd64-rmdw7 1/1 Running 1 44m 192.168.100.199 nodesatu <none> <none>
</span><span>kube-proxy-hgkn9 1/1 Running 0 44m 192.168.100.199 nodesatu <none> <none>
</span><span>kube-proxy-lc5ps 1/1 Running 0 77m 192.168.100.198 master <none> <none>
</span><span>kube-scheduler-master 1/1 Running 0 77m 192.168.100.198 master <none> <none>
</span></code></pre>
<p>Dari data diatas, semua pod running. Aku asumsikan semua beres.</p>
<h1 id="c-pasca-setup-cluster">C. Pasca Setup Cluster</h1>
<p>Setelah cluster berjalan, aku lanjutkan install aplikasi di atas cluster kubernetes.
Kita kembali ke master, dan install-install dari master.</p>
<h2 id="c-1-install-helm3">C.1 Install Helm3</h2>
<p>Helm v3 ini akan membatu banget untuk install-install aplikasi diatas cluster kubernetes.</p>
<p>bash
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3</p>
<p>chmod 700 get_helm.sh</p>
<p>./get_helm.sh</p>
<p>helm repo add stable https://kubernetes-charts.storage.googleapis.com/</p>
<p>helm repo update</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>
</span><span>
</span><span>
</span><span>## C.2 Install metallb
</span><span>
</span><span>Ikuti https://metallb.universe.tf/installation/
</span><span>
</span><span>Krn cluster yg kubuat di vm local, dan gak punya dedicated LB, maka aku butuh metallb untuk assign IP ke service bertipe LoadBalancer
</span><span>
</span><span>bash
</span><span>kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.9.3/manifests/namespace.yaml
</span><span>
</span><span>kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.9.3/manifests/metallb.yaml
</span><span>
</span><span>kubectl create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)"
</span></code></pre>
<p>Bikin configmap untuk metallb, silakan merujuk ke <a href="https://metallb.universe.tf/configuration/#layer-2-configuration">https://metallb.universe.tf/configuration/#layer-2-configuration</a></p>
<pre data-lang="yaml" style="background-color:#fcf0ca;color:#282828aa;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span style="color:#79740e;">nano metallb-configmap.yaml
</span><span style="font-style:italic;color:#928374;"># isinya sbb:
</span><span style="font-weight:bold;color:#407959;">apiVersion</span><span>: </span><span style="color:#79740e;">v1
</span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">ConfigMap
</span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">namespace</span><span>: </span><span style="color:#79740e;">metallb-system
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">config
</span><span style="font-weight:bold;color:#407959;">data</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">config</span><span>: </span><span style="color:#9d0006;">|
</span><span style="color:#79740e;"> address-pools:
</span><span style="color:#79740e;"> - name: default
</span><span style="color:#79740e;"> protocol: layer2
</span><span style="color:#79740e;"> addresses:
</span><span style="color:#79740e;"> - 192.168.100.30-192.168.100.40
</span></code></pre>
<p>Yang perlu diperhatikan adalah <code>192.168.100.30-192.168.100.40</code>, IP ini aku kasih range dari router, ya krn ini VM di local. Kalau di cloud/datacenter range ip tersebut harus ip public supaya service bisa dijangkau dari luar.</p>
<p>bash
kubectl apply -f metallb-configmap.yaml</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>
</span><span>Verifikasi hasil install metallb
</span><span>
</span><span>bash
</span><span>root@master:~# kubectl -n metallb-system get po -o wide
</span><span>NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
</span><span>controller-57f648cb96-b5llj 1/1 Running 0 33m 10.244.1.2 nodesatu <none> <none>
</span><span>speaker-csgx5 1/1 Running 0 33m 192.168.100.199 nodesatu <none> <none>
</span><span>speaker-mrv7x 1/1 Running 0 33m 192.168.100.198 master <none> <none>
</span></code></pre>
<h2 id="c-3-install-nginx-ingress-controller">C.3 Install Nginx Ingress Controller</h2>
<p>Ikuti https://kubernetes.github.io/ingress-nginx/deploy/#using-helm</p>
<p>Ingress controller ini membantu untuk expose service ke luar cluster, misalnya expose web service via domain.</p>
<p>Nginx Ingress Controller hanyalah satu dari sekian banyak Ingress Controller. Selain nginx ada Traefik, HAProxy, dll. Aku sendiri selama ini pakai Traefik v1.7.24 di production. Dah kali ini aku akan pakai Nginx</p>
<p>bash
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm install my-release ingress-nginx/ingress-nginx</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>
</span><span>Perintah diatas akan install nginx di namespace default, kita check:
</span><span>
</span><span>bash
</span><span>@master:~# kubectl -n default get po,svc -o wide
</span><span>NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
</span><span>pod/my-release-ingress-nginx-controller-7fcf9d598b-k68gs 1/1 Running 0 34m 10.244.1.4 nodesatu <none> <none>
</span><span>
</span><span>NAME TYPE CLUSTER-IP PORT(S) AGE SELECTOR
</span><span>service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 85m <none>
</span><span>service/my-release-ingress-nginx-controller LoadBalancer 10.110.208.65 192.168.100.30 80:30509/TCP,443:30954/TCP 34m app.kubernetes.io/component=controller,app.kubernetes.io/instance=my-release,app.kubernetes.io/name=ingress-nginx
</span><span>service/my-release-ingress-nginx-controller-admission ClusterIP 10.104.254.133 <none> 443/TCP 34m app.kubernetes.io/component=controller,app.kubernetes.io/instance=my-release,app.kubernetes.io/name=ingress-nginx
</span></code></pre>
<p>Berkat bantuan metallb, EXTERNAL-IP dari <code>service/my-release-ingress-nginx-controller</code> tidak pending. Dalam hal ini dia mendapatkan IP 192.168.100.30. IP tsb kita asumsikan IP public yg mana akan dimasukan ke DNS A Record</p>
<p>Untuk memastikan ingress controllernya berfungsi, aku akan test dari luar cluster yakni dari PC.</p>
<p>bash
➜ ~ curl 192.168.100.30</p>
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.19.0</center>
</body>
</html>
```
<p>Kita coba deploy aplikasi <code>whoareyou</code></p>
<p>Isi dari <code>whoareyou.yaml</code></p>
<pre data-lang="yaml" style="background-color:#fcf0ca;color:#282828aa;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span style="font-weight:bold;color:#407959;">apiVersion</span><span>: </span><span style="color:#79740e;">apps/v1
</span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">Deployment
</span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">whoareyou-deployment
</span><span style="font-weight:bold;color:#407959;">spec</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">replicas</span><span>: </span><span style="color:#8f3f71;">2
</span><span> </span><span style="font-weight:bold;color:#407959;">selector</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">matchLabels</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">app</span><span>: </span><span style="color:#79740e;">whoareyou
</span><span> </span><span style="font-weight:bold;color:#407959;">template</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">labels</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">app</span><span>: </span><span style="color:#79740e;">whoareyou
</span><span> </span><span style="font-weight:bold;color:#407959;">spec</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">containers</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">whoareyou-container
</span><span> </span><span style="font-weight:bold;color:#407959;">image</span><span>: </span><span style="color:#79740e;">containous/whoami
</span><span style="color:#407959;">---
</span><span style="font-weight:bold;color:#407959;">apiVersion</span><span>: </span><span style="color:#79740e;">v1
</span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">Service
</span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">whoareyou-service
</span><span style="font-weight:bold;color:#407959;">spec</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">ports</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">http
</span><span> </span><span style="font-weight:bold;color:#407959;">targetPort</span><span>: </span><span style="color:#8f3f71;">80
</span><span> </span><span style="font-weight:bold;color:#407959;">port</span><span>: </span><span style="color:#8f3f71;">80
</span><span> </span><span style="font-weight:bold;color:#407959;">selector</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">app</span><span>: </span><span style="color:#79740e;">whoareyou
</span><span style="color:#407959;">---
</span><span style="font-weight:bold;color:#407959;">apiVersion</span><span>: </span><span style="color:#79740e;">networking.k8s.io/v1beta1
</span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">Ingress
</span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">whoareyou-ingress
</span><span> </span><span style="font-weight:bold;color:#407959;">annotations</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">kubernetes.io/ingress.class</span><span>: </span><span style="color:#79740e;">"nginx"
</span><span style="font-weight:bold;color:#407959;">spec</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">rules</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">host</span><span>: </span><span style="color:#79740e;">whoareyou.kvm.local
</span><span> </span><span style="font-weight:bold;color:#407959;">http</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">paths</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">path</span><span>: </span><span style="color:#79740e;">/
</span><span> </span><span style="font-weight:bold;color:#407959;">backend</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">serviceName</span><span>: </span><span style="color:#79740e;">whoareyou-service
</span><span> </span><span style="font-weight:bold;color:#407959;">servicePort</span><span>: </span><span style="color:#79740e;">http
</span></code></pre>
<p>bash
kubectl apply -f whoareyou.yaml</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>
</span><span>Verifikasi hasil deploy:
</span><span>
</span><span>bash
</span><span>root@master:~# kubectl -n default get po,svc,ingress
</span><span>NAME READY STATUS RESTARTS AGE
</span><span>pod/my-release-ingress-nginx-controller-7fcf9d598b-k68gs 1/1 Running 0 45m
</span><span>pod/whoareyou-deployment-74bff9c468-mlnjd 1/1 Running 0 110s
</span><span>pod/whoareyou-deployment-74bff9c468-p5bkp 1/1 Running 0 110s
</span><span>
</span><span>NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
</span><span>service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 97m
</span><span>service/my-release-ingress-nginx-controller LoadBalancer 10.110.208.65 192.168.100.30 80:30509/TCP,443:30954/TCP 45m
</span><span>service/my-release-ingress-nginx-controller-admission ClusterIP 10.104.254.133 <none> 443/TCP 45m
</span><span>service/whoareyou-service ClusterIP 10.108.79.85 <none> 80/TCP 110s
</span><span>
</span><span>NAME CLASS HOSTS ADDRESS PORTS AGE
</span><span>ingress.extensions/whoareyou-ingress <none> whoareyou.kvm.local 192.168.100.30 80 110s
</span></code></pre>
<p>Kita test hasil deploynya. Anggaplah <code>whoareyou.kvm.local</code> nama domain yg kita set dan <code>192.168.100.30</code> adalah public ip. Krn ini di local, cara testnya bisa kita masukin ke /etc/hosts komputer di luar cluster. Atau pakai curl dengan param header host. Disini aku test pakai curl</p>
<p>bash
➜ ~ curl -H "Host: whoareyou.kvm.local" 192.168.100.30
Hostname: whoareyou-deployment-74bff9c468-mlnjd
IP: 127.0.0.1
IP: 10.244.1.7
RemoteAddr: 10.244.1.4:33058
GET / HTTP/1.1
Host: whoareyou.kvm.local
User-Agent: curl/7.70.0
Accept: <em>/</em>
X-Forwarded-For: 10.244.1.1
X-Forwarded-Host: whoareyou.kvm.local
X-Forwarded-Port: 80
X-Forwarded-Proto: http
X-Real-Ip: 10.244.1.1
X-Request-Id: bce405ea511051351247e01746104180
X-Scheme: http</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>
</span><span>Sip, sukses. Yg keluar adalah output dari pod whoareyou.
</span><span>
</span><span>Bagaimana kalau kita pakai nama domain yg lain?
</span><span>
</span><span>bash
</span><span>➜ ~ curl -H "Host: sembarangan.com" 192.168.100.30
</span><span><html>
</span><span><head><title>404 Not Found</title></head>
</span><span><body>
</span><span><center><h1>404 Not Found</h1></center>
</span><span><hr><center>nginx/1.19.0</center>
</span><span></body>
</span><span></html>
</span></code></pre>
<p>Outputnya adalah 404, karena ingress rule untuk domain sembarangan.com tidak ada.</p>
<p>Kesimpulannya adalah, kubeadm ini sangat memudahkan kita untuk setup kubernetes cluster. Banyak magic-nya. Aku senang dengan adanya kubeadm</p>
awk print kolom pertama dan baris pertama
2020-06-25T16:09:35+07:00
2020-06-25T16:09:35+07:00
Unknown
https://www.sumarsono.com/awk-print-kolom-pertama-dan-baris-pertama/
<p>Belajar print IP addr yang ada di baris pertama dan kolom pertama, pakai getent dan awk.</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>➜ ~ getent ahosts sumarsono.com
</span><span>206.189.73.52 STREAM sumarsono.com
</span><span>206.189.73.52 DGRAM
</span><span>206.189.73.52 RAW
</span><span>2604:a880:400:d1::895:1 STREAM
</span><span>2604:a880:400:d1::895:1 DGRAM
</span><span>2604:a880:400:d1::895:1 RAW
</span></code></pre>
<p>Step 1: Print IP addr aja. Pakai awk untuk print kolom pertama,</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>➜ ~ getent ahosts sumarsono.com | awk '{print $1}'
</span><span>206.189.73.52
</span><span>206.189.73.52
</span><span>206.189.73.52
</span><span>2604:a880:400:d1::895:1
</span><span>2604:a880:400:d1::895:1
</span><span>2604:a880:400:d1::895:1
</span></code></pre>
<p>Step 2: Print IP addr dari baris pertama dan kolom pertama,</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>➜ ~ getent ahosts sumarsono.com | awk 'NR==1{print $1}'
</span><span>206.189.73.52
</span></code></pre>
Debian cek ssh failed login
2020-06-10T13:04:40+07:00
2020-06-10T13:04:40+07:00
Unknown
https://www.sumarsono.com/debian-cek-ssh-failed-login/
<p>Bagi yang baru setup VPS dan belum me-nonaktifkan password auth ssh, pasti langsung diketuk-ketuk sama botnet.</p>
<p>Kita bisa cek log auth ssh:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span># check failed login
</span><span>cat /var/log/auth.log | egrep 'sshd.*fail|sshd.*invalid'
</span><span>
</span><span># check success login
</span><span>cat /var/log/auth.log | grep 'sshd.*opened'
</span></code></pre>
<p>Ketika setup server yang open public, disarankan untuk:</p>
<ol>
<li>Disable PasswordAuthentication ssh</li>
<li>Disable PermitRootLogin ssh</li>
<li>Aktifkan PubkeyAuthentication dan jangan lupa add PC kita, jangan sampai terjebak gak bisa ssh sama sekali</li>
<li>Ganti port ssh, gunakan selain port 22</li>
</ol>
<p>Dengan begitu, ssh akan jalan di port non standar ssh, auth wajib pakai public key, login pakai password engga bisa.</p>
HAProxy X-XSS-Protection
2020-06-10T11:52:19+07:00
2020-06-10T11:52:19+07:00
Unknown
https://www.sumarsono.com/haproxy-x-xss-protection/
<p>Untuk set response header <code>X-XSS-Protection: 1; mode=block</code> pada haproxy, cukup tambahkan konfigurasi berikut ini kedalam section <strong>frontend</strong>:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>rspdel X-XSS-Protection:\ 1;\ mode=block
</span><span>rspadd X-XSS-Protection:\ 1;\ mode=block
</span></code></pre>
HAProxy X-Frame-Options
2020-06-10T11:52:10+07:00
2020-06-10T11:52:10+07:00
Unknown
https://www.sumarsono.com/haproxy-x-frame-options/
<p>Untuk set response header <code>X-Frame-Options: SAMEORIGIN</code> pada haproxy, cukup tambahkan konfigurasi berikut ke <strong>frontend</strong> section:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span> rspdel X-Frame-Options:\ SAMEORIGIN
</span><span> rspadd X-Frame-Options:\ SAMEORIGIN
</span></code></pre>
HAProxy X-Content-Type-Options nosniff
2020-06-10T11:51:43+07:00
2020-06-10T11:51:43+07:00
Unknown
https://www.sumarsono.com/haproxy-x-content-type-options-nosniff/
<p>Untuk set response header <code>X-Content-Type-Options: nosniff</code> pada haproxy, tambahkan konfigurasi begrikut ke bagian <strong>frontend</strong>:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>http-response set-header X-Content-Type-Options nosniff
</span></code></pre>
HAProxy SSL A+
2020-06-10T11:39:37+07:00
2020-06-10T11:39:37+07:00
Unknown
https://www.sumarsono.com/haproxy-ssl-a/
<p>Cara mendapatkan skor SSL A+ dari SSL Labs untuk haproxy</p>
<p><strong>global</strong> section, tambahkan:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span> ssl-default-bind-options no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets
</span></code></pre>
<p><strong>frontend https</strong>, tambahkan:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span> bind *:443 ssl crt /etc/ssl/jekyll.nalakawula.com.pem alpn http/1.1,h2
</span><span> # HSTS header (1 year = 31540000 seconds)
</span><span> http-response set-header Strict-Transport-Security max-age=31540000
</span></code></pre>
Menambahkan Cloudflare Origin CA certificate Ke Traefik Kubernetes Ingress
2020-06-10T10:13:11+07:00
2020-06-10T10:13:11+07:00
Unknown
https://www.sumarsono.com/menambahkan-cloudflare-origin-ca-certificate-ke-traefik-kubernetes-ingress/
<p>Ceritanya, aku pengen nyobain End-to-end HTTPS pakai Cloudflare dengan mode <a href="https://support.cloudflare.com/hc/en-us/articles/200170416-End-to-end-HTTPS-with-Cloudflare-Part-3-SSL-options#h_8afd8a8d-382d-4694-a2b2-44cbc9f637ef">Full (strict)</a>. Alasannya, karena aku pakai Traefik v1.7.24 sebagai ingress controller, dan aku ingin pakai SSL certificate dari cloudflare. Nah si traefik ini sudah dikonfigurasi untuk pakai SSL certificate dari Let's Encrypt pakai OnHostRule. Masalahnya adalah ketika aku aktifkan HTTP cloudflare maka traefik akan gagal ketika validasi ke server let's encrypt.</p>
<p>Salah satu cara agar traefik tidak request sertifikat ke let's encrypt adalah dengan cara mendefinisikan tls.secreteName di spec Ingress-nya:</p>
<pre data-lang="yaml" style="background-color:#fcf0ca;color:#282828aa;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span> </span><span style="font-weight:bold;color:#407959;">tls</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">secretName</span><span>: </span><span style="color:#79740e;">sertifikatku-tls-cert
</span></code></pre>
<p>Kenapa sih kok ribet bener? Yah namanya juga lagi belajar, explorasi.</p>
<p>Pertama, generate <strong>Origin Certificates</strong> dari cloudflare:</p>
<p><strong>Menu SSL/TLS > Origin Server > Origin Certificates > Create Certficate</strong></p>
<p>Copas dan simpan certificate:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>-----BEGIN CERTIFICATE-----
</span><span>sampai
</span><span>-----END CERTIFICATE-----
</span></code></pre>
<p>Simpan aja dengan nama domainku.crt</p>
<p>Selanjutnya copas dan simpan private key:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>-----BEGIN PRIVATE KEY-----
</span><span>sampai
</span><span>-----END PRIVATE KEY-----
</span></code></pre>
<p>Simpan aja dengan nama domainku.key</p>
<p>Kedua, bikin secret tls pakai kubectl:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">kubectl -n development create secret tls domainku-tls-cert --key</span><span style="color:#b23c15;">=</span><span style="color:#282828;">domainku.key --cert</span><span style="color:#b23c15;">=</span><span style="color:#282828;">domainku.crt
</span></code></pre>
<p><strong>Note</strong>: </p>
<p>Secret API objects reside in a namespace. They <strong>can only be referenced by pods in that same namespace</strong>. Basically, </p>
<p><a href="https://kubernetes.io/docs/concepts/configuration/secret/#details">https://kubernetes.io/docs/concepts/configuration/secret/#details</a></p>
<p>Terakhir bikin ingress manifest domainku.com.ingress.yaml:</p>
<pre data-lang="yaml" style="background-color:#fcf0ca;color:#282828aa;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span style="font-weight:bold;color:#407959;">apiVersion</span><span>: </span><span style="color:#79740e;">extensions/v1beta1
</span><span style="font-weight:bold;color:#407959;">kind</span><span>: </span><span style="color:#79740e;">Ingress
</span><span style="font-weight:bold;color:#407959;">metadata</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">namespace</span><span>: </span><span style="color:#79740e;">development
</span><span> </span><span style="font-weight:bold;color:#407959;">name</span><span>: </span><span style="color:#79740e;">domainku.com
</span><span> </span><span style="font-weight:bold;color:#407959;">annotations</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">kubernetes.io/ingress.class</span><span>: </span><span style="color:#79740e;">traefik
</span><span> </span><span style="font-weight:bold;color:#407959;">ingress.kubernetes.io/browser-xss-filter</span><span>: </span><span style="color:#79740e;">'true'
</span><span> </span><span style="font-weight:bold;color:#407959;">ingress.kubernetes.io/content-type-nosniff</span><span>: </span><span style="color:#79740e;">'true'
</span><span> </span><span style="font-weight:bold;color:#407959;">traefik.ingress.kubernetes.io/redirect-permanent</span><span>: </span><span style="color:#79740e;">"true"
</span><span> </span><span style="font-weight:bold;color:#407959;">traefik.ingress.kubernetes.io/redirect-regex</span><span>: </span><span style="color:#79740e;">^https?://(www\.)?(.*)
</span><span> </span><span style="font-weight:bold;color:#407959;">traefik.ingress.kubernetes.io/redirect-replacement</span><span>: </span><span style="color:#79740e;">https://${2}
</span><span> </span><span style="font-weight:bold;color:#407959;">ingress.kubernetes.io/force-hsts</span><span>: </span><span style="color:#79740e;">"true"
</span><span> </span><span style="font-weight:bold;color:#407959;">ingress.kubernetes.io/hsts-max-age</span><span>: </span><span style="color:#79740e;">"2592000"
</span><span> </span><span style="font-weight:bold;color:#407959;">ingress.kubernetes.io/hsts-include-subdomains</span><span>: </span><span style="color:#79740e;">"true"
</span><span> </span><span style="font-weight:bold;color:#407959;">ingress.kubernetes.io/hsts-preload</span><span>: </span><span style="color:#79740e;">"false"
</span><span> </span><span style="font-weight:bold;color:#407959;">ingress.kubernetes.io/frame-deny</span><span>: </span><span style="color:#79740e;">"true"
</span><span> </span><span style="font-weight:bold;color:#407959;">ingress.kubernetes.io/custom-frame-options-value</span><span>: </span><span style="color:#79740e;">"SAMEORIGIN"
</span><span> </span><span style="font-weight:bold;color:#407959;">ingress.kubernetes.io/content-security-policy</span><span>: </span><span style="color:#79740e;">upgrade-insecure-requests
</span><span> </span><span style="font-weight:bold;color:#407959;">traefik.ingress.kubernetes.io/buffering</span><span>: </span><span style="color:#9d0006;">|-
</span><span style="color:#79740e;"> maxrequestbodybytes: 10485760
</span><span style="color:#79740e;"> memrequestbodybytes: 2097153
</span><span style="color:#79740e;"> maxresponsebodybytes: 10485761
</span><span style="color:#79740e;"> memresponsebodybytes: 2097152
</span><span style="color:#79740e;"> retryexpression: IsNetworkError() && Attempts() <= 2
</span><span> </span><span style="font-weight:bold;color:#407959;">traefik.ingress.kubernetes.io/rate-limit</span><span>: </span><span style="color:#9d0006;">|
</span><span style="color:#79740e;"> extractorfunc: client.ip
</span><span style="color:#79740e;"> rateset:
</span><span style="color:#79740e;"> myratelimit:
</span><span style="color:#79740e;"> period: 1s
</span><span style="color:#79740e;"> average: 50
</span><span style="color:#79740e;"> burst: 100
</span><span style="font-weight:bold;color:#407959;">spec</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">rules</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">host</span><span>: </span><span style="color:#79740e;">domainku.com
</span><span> </span><span style="font-weight:bold;color:#407959;">http</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">paths</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">path</span><span>: </span><span style="color:#79740e;">/
</span><span> </span><span style="font-weight:bold;color:#407959;">backend</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">serviceName</span><span>: </span><span style="color:#79740e;">myservice007
</span><span> </span><span style="font-weight:bold;color:#407959;">servicePort</span><span>: </span><span style="color:#8f3f71;">80
</span><span> </span><span style="font-weight:bold;color:#407959;">tls</span><span>:
</span><span> - </span><span style="font-weight:bold;color:#407959;">secretName</span><span>: </span><span style="color:#79740e;">domainku-tls-cert
</span></code></pre>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">kubectl apply -f domainku.com.ingress.yaml
</span></code></pre>
<p>Selesai, dengan begini si traefik tidak akan request sertifikat ke let's encrypt dan aku bisa aktifkan awan kuning cloudflare dengan mode Full (strict)</p>
<p>~</p>
Cara Ganti Timezone Debian 10
2020-06-04T15:34:24+07:00
2020-06-04T15:34:24+07:00
Unknown
https://www.sumarsono.com/cara-ganti-timezone-debian-10/
<p>Cara mengganti timezone Debian 10 sangatlah mudah. Cukup pakai command <code>timedatectl</code>.
Berikut ini demonstrasi mengganti timzone Debian 10 menggunakan <code>timedatectl</code>:</p>
<p>Sebelum timezone debian 10 diganti:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sumar@gw:~$ timedatectl
</span><span> Local time: Thu 2020-06-04 07:31:04 UTC
</span><span> Universal time: Thu 2020-06-04 07:31:04 UTC
</span><span> RTC time: Thu 2020-06-04 07:31:05
</span><span> Time zone: Etc/UTC (UTC, +0000)
</span><span>System clock synchronized: yes
</span><span> NTP service: active
</span><span> RTC in local TZ: no
</span></code></pre>
<p>Mengganti timezone Debian 10 menjadi Asia/Jakarta:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>root@gw:/home/sumar# timedatectl set-timezone Asia/Jakarta
</span></code></pre>
<p>Setelah timezone Debian 10 diganti menjadi Asia/Jakarta:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>root@gw:/home/sumar# timedatectl set-timezone Asia/Jakarta
</span><span>root@gw:/home/sumar# timedatectl
</span><span> Local time: Thu 2020-06-04 14:31:45 WIB
</span><span> Universal time: Thu 2020-06-04 07:31:45 UTC
</span><span> RTC time: Thu 2020-06-04 07:31:46
</span><span> Time zone: Asia/Jakarta (WIB, +07:00)
</span><span>System clock synchronized: yes
</span><span> NTP service: active
</span><span> RTC in local TZ: no
</span></code></pre>
<p>Mudah sekali, cuma modal <code>timedatectl set-timezone</code></p>
<p>~</p>
python3 echo server
2020-06-03T13:37:44+07:00
2020-06-03T13:37:44+07:00
Unknown
https://www.sumarsono.com/python3-echo-server/
<p>Script python3 buat balikin request headers ke client sebagai respons header. Sanagt berguna untuk debugging.</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span># echo.py
</span><span>import http.server as SimpleHTTPServer
</span><span>import socketserver as SocketServer
</span><span>import logging
</span><span>
</span><span>PORT = 8000
</span><span>
</span><span>class GetHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
</span><span>
</span><span> def do_GET(self):
</span><span> self.send_head()
</span><span> for h in self.headers:
</span><span> self.send_header(h, self.headers[h])
</span><span> self.end_headers()
</span><span> self.send_response(200, "")
</span><span>
</span><span>
</span><span>Handler = GetHandler
</span><span>httpd = SocketServer.TCPServer(("", PORT), Handler)
</span><span>
</span><span>httpd.serve_forever()
</span></code></pre>
<p>run pakai:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>python3 echo.py
</span></code></pre>
<p>test pakai:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>curl -s -H "X-Custom-Header: hoya" http://192.168.122.151:8000/
</span><span>
</span><span>
</span><span># response:
</span><span>Host: 192.168.122.151:8000
</span><span>User-Agent: curl/7.70.0
</span><span>Accept: */*
</span><span>X-Custom-Header: hoya
</span></code></pre>
<p>Sumber: <a href="https://gist.github.com/phrawzty/62540f146ee5e74ea1ab#gistcomment-2358615">simple python http server to dump request headers</a></p>
Install Mongodb Ubuntu 16.04 dan Setup RBAC
2020-04-27T14:14:41+07:00
2020-04-27T14:14:41+07:00
Unknown
https://www.sumarsono.com/install-mongodb-ubuntu-16-04-dan-setup-rbac/
<p>Quick note install mongodb di ubuntu 16.04 sekaligus set RBAC-nya. Panduan install mongodb di official site engga langsung ngasih petunjuk untuk setup RBAC. Jadi kutulis ini sebagai catatan pribadi agar tidak lupa.</p>
<p>Tambahkan repo mongodb ubuntu 16.04:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>wget -qO - https://www.mongodb.org/static/pgp/server-4.2.asc | sudo apt-key add -
</span><span>echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/4.2 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.2.list
</span></code></pre>
<p>Install mongodb di ubuntu 16.04 pakai apt:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo apt-get update
</span><span>sudo apt-get install -y mongodb-org
</span></code></pre>
<p>Hold paket mongodb supaya tidak auto update:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>echo "mongodb-org hold" | sudo dpkg --set-selections
</span><span>echo "mongodb-org-server hold" | sudo dpkg --set-selections
</span><span>echo "mongodb-org-shell hold" | sudo dpkg --set-selections
</span><span>echo "mongodb-org-mongos hold" | sudo dpkg --set-selections
</span><span>echo "mongodb-org-tools hold" | sudo dpkg --set-selections
</span></code></pre>
<p>Start dan enable service mongod:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo systemctl start mongod
</span><span>sudo systemctl status mongod
</span><span>sudo systemctl enable mongod
</span></code></pre>
<p>Setup RBAC mongodb dengan cara enbale auth di conf nya:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo nano /etc/mongod.conf
</span><span>
</span><span># set bagian ini:
</span><span>security:
</span><span> authorization: enabled
</span></code></pre>
<p>Restart service mongodb:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo systemctl restart mongod
</span><span>sudo systemctl status mongod
</span></code></pre>
<p>Setup auth user dengan cara masuk ke mongo shell, dalam hal ini aku akan buat user <code>example-admin</code> dengan passwd <code>example-admin-passwd</code> sekaligus set role sebagai admin untuk semua database:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>mongo
</span><span>
</span><span>> //line ini kebawah jalan di dalam mongo shell
</span><span>> use admin
</span><span>> db.createUser({user: "example-admin", pwd: "example-admin-passwd", roles:[{role: "userAdminAnyDatabase", db: "admin"}]})
</span><span>> // outputnya seperti ini:
</span><span>Successfully added user: {
</span><span> "user" : "example-admin",
</span><span> "roles" : [
</span><span> {
</span><span> "role" : "userAdminAnyDatabase",
</span><span> "db" : "admin"
</span><span> }
</span><span> ]
</span><span>}
</span><span>
</span><span>> quit()
</span></code></pre>
<p>Selanjutnya bikin user biasa untuk app/developer dengan cara masuk mongo shell pakai user <code>example-admin</code>. Dalam hal ini aku akan bikin user <code>example-user</code> dengan passwd <code>example-passwd</code> dan role read write untuk database <code>exampleDB</code>:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>mongo -u example-admin -p --authenticationDatabase admin
</span><span>
</span><span>> // line ini kebawah jalan di dalam mongo shell
</span><span>> use user-data
</span><span>> db.createUser({user: "example-user", pwd: "example-password", roles:[{role: "read", db: "user-data"}, {role:"readWrite", db: "exampleDB"}]})
</span><span>> quit()
</span></code></pre>
<p>Tes bikin data dan collection pakai user biasa <code>example-user</code>:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>mongo -u example-user -p --authenticationDatabase user-data
</span><span>
</span><span>> // line ini kebawah jalan di dalam mongo shell
</span><span>> use exampleDB
</span><span>> db.createCollection("exampleCollection", {capped: false})
</span><span>> var a = { name : "John Doe", attributes: { age : 30, address : "123 Main St", phone : 8675309 }}
</span><span>> var b = { name : "Jane Doe", attributes: { age : 29, address : "321 Main Rd", favorites : { food : "Spaghetti", animal : "Dog" } }}
</span><span>> db.exampleCollection.insert(a)
</span><span>> db.exampleCollection.insert(b)
</span><span>> show collections
</span><span>> db.exampleCollection.find()
</span><span>> db.exampleCollection.find({"name" : "John Doe"})
</span></code></pre>
<p>Kalau sudah setup RBAC, supaya klien bisa konek ke mongodb maka harus pakai url berikut:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>
</span></code></pre>
Password HG8245H Indihome 2020
2020-04-18T14:50:13+07:00
2020-04-18T14:50:13+07:00
Unknown
https://www.sumarsono.com/password-hg8245h-indihome-2020/
<p>Router Huawei HG8245H bawaan indihome mempunyai dua user, admin dan super admin. Password Huawei HG8245H yang berubah itu password untuk super admin.
Awalnya aku engga tahu kalau berubah, baru tahu hari ini karena gagal login. Mungkin password Huawei HG8245H diubah oleh pihak telkom karena alasan keamanan.
Lagipula user biasa harusnya engga butuh password untuk super admin.</p>
<p>Berikut ini adalah username dan password admin Huawei HG8245H indihome:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>username: Admin
</span><span>password: admin
</span></code></pre>
<p>Dan berikut ini adalah username dan password super admin Huawei HG8245H indihome:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>username: Support
</span><span>password lama: theworldinyourhand
</span><span>password baru: zep2kjzol
</span></code></pre>
<p>Dari username dan password HG8245H indihome tersebut perlu diperhatikan bagian username, huruf awal memang kapital. </p>
AdguardHome Resolve Local Domain Name
2020-04-17T11:18:39+07:00
2020-04-17T11:18:39+07:00
Unknown
https://www.sumarsono.com/adguardhome-resolve-local-domain-name/
<p>Saat artikel ini ditulis, aku sedang menjajal AdguardHome. AdguardHome adalah Network-wide ads & trackers blocking DNS server layaknya PiHole. Sejujurnya, aku udah <em>pewe</em> pakai PiHole.
Tapi ya engga ada salahnya jajal AguardHome <del>for science</del>. Aku mencoba install AdguardHome di VM, mengikuti <a href="https://github.com/AdguardTeam/AdGuardHome/wiki/Getting-Started#limitations">panduan mereka</a>. Engga ada kendala sama sekali.</p>
<p>Setelah seharian nyobain AdguarHome, ada satu yang ketinggalan. Bagaimana caranya aku resolve intranet domain <code>*.local</code>? contohnya aku mau resolve <code>sysadmin.ded.local</code>.
Dulu pas pakai PiHole, bisa dengan mudah diset di konfigurasi dnsmasq-nya. Di AguardHome ini ternyata sudah difasilitasi dengan cara masuk <strong>Settings > DNS settings > Upstream DNS servers</strong>. Upstream DNS servers aku isi:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>https://dns.quad9.net/dns-query
</span><span>[/local/]127.0.0.1:54
</span></code></pre>
<p>Kalau diterjemahkan secara bodohnya si: Semua query domain arahkan ke https://dns.quad9.net/dns-query (ini DNS-over-HTTPS) kecuali <code>*.local</code>. Untuk <code>*.local</code> query ke 127.0.0.1:54.</p>
<p>Hmm, simple ya? Tapi aku jadi butuh bikin dns server lagi. Mau install-install lagi males. Cara tercepat adalah pakai [coredns]({% post_url 2019-11-05-cara-mudah-bikin-dns-server-lokal-pakai-coredns %}). Cukup download single binary, run and forget.
Jadi supaya AdguardHome bisa resolve <code>*.local</code> aku harus kombinasikan dengan <code>coredns</code> yang jalan di port 54. Berikut ini konfigurasi coredns yang kupakai,</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>$ cat Corefile
</span><span>.:54 {
</span><span> forward . 9.9.9.9 {
</span><span> except ded.local
</span><span> }
</span><span> log
</span><span> errors
</span><span>}
</span><span>
</span><span>ded.local:54 {
</span><span> log
</span><span> errors
</span><span> file /opt/coredns/ded.local.db
</span><span>}
</span></code></pre>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>cat /opt/coredns/ded.local.db
</span><span>ded.local. IN SOA dns.ded.local. sumar.ded.local. 2020041617 7200 3600 1209600 3600
</span><span>sysadmin.ded.local. IN A 192.168.1.26
</span></code></pre>
<p>Kalau coba test query pakai drill:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>$ drill @192.168.1.195 sysadmin.ded.local
</span><span>;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 34403
</span><span>;; flags: qr aa rd ; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
</span><span>;; QUESTION SECTION:
</span><span>;; sysadmin.ded.local. IN A
</span><span>
</span><span>;; ANSWER SECTION:
</span><span>sysadmin.ded.local. 0 IN A 192.168.1.26
</span><span>
</span><span>;; AUTHORITY SECTION:
</span><span>
</span><span>;; ADDITIONAL SECTION:
</span><span>
</span><span>;; Query time: 2 msec
</span><span>;; SERVER: 192.168.1.195
</span><span>;; WHEN: Fri Apr 17 11:34:11 2020
</span><span>;; MSG SIZE rcvd: 52
</span></code></pre>
<ul>
<li>192.168.1.195: IP Address AdguardHome</li>
<li>sysadmin.ded.local: Domain yang kita coba resolve lewat AdguardHomwe</li>
</ul>
<p>Oke sip, sekarang AdguardHome bisa resolve domain intranet <code>*.local</code>.</p>
<p>Cool~</p>
Autostart VM VirtualBox
2020-04-17T09:46:41+07:00
2020-04-17T09:46:41+07:00
Unknown
https://www.sumarsono.com/autostart-vm-virtualbox/
<p>Cara auto start vm virtualbox ketika komputer dinyalakan sangatlah mudah. Di <a href="https://docs.oracle.com/en/virtualization/virtualbox/6.1/admin/autostart.html">dokumentasi resmi virtualbox</a> juga ada. Silakan cek disana, kalau penasaran.
Aku mau nulis cara yang tidak tertulis di dokumentasi resmi virtualbox. Dalam konteks ini, aku pakai PC dengan OS Manjaro Linux dan VirtualBox Version 6.1.4 r136177.</p>
<p>Mayoritas distribusi linux anyar pakai systemd, oleh sebab itu aku mau vm yang ada didalam virtualbox autostart pakai service systemd. Tujuannya biar lebih nyaman aja. Berikut ini langkah yang ku tempuh supaya bisa auto start vm virtualbox ketika komputer dinyalakan.</p>
<p>Pertama, kita cari tahu nama vm yang mau di set autostart:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>VBoxManage -nologo list vms
</span><span>
</span><span># output
</span><span>"Pihole" {292c0973-6f9c-458f-b8d1-fbf9603af5e3}
</span><span>"AdguardHome" {eb71cc73-b7cb-41d9-87f7-89876d5f1132}
</span></code></pre>
<p>VM yang mau aku auto start adalah <code>AdguardHome</code></p>
<p>Kedua, aku bikin service systemd</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo nano /etc/systemd/system/vm-AdguardHome.service
</span></code></pre>
<p>Isi dari /etc/systemd/system/vm-AdguardHome.service</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>[Unit]
</span><span>Description=VirtualBox AdguardHome
</span><span>After=network.target virtualbox.service
</span><span>Before=runlevel2.target shutdown.target
</span><span>
</span><span>[Service]
</span><span>User=sumarsono
</span><span>Group=vboxusers
</span><span>Type=forking
</span><span>Restart=no
</span><span>TimeoutSec=5min
</span><span>IgnoreSIGPIPE=no
</span><span>KillMode=process
</span><span>GuessMainPID=no
</span><span>RemainAfterExit=yes
</span><span>
</span><span>ExecStart=/usr/bin/VBoxManage startvm AdguardHome --type headless
</span><span>ExecStop=/usr/bin/VBoxManage controlvm AdguardHome acpipowerbutton
</span><span>
</span><span>[Install]
</span><span>WantedBy=multi-user.target
</span></code></pre>
<p>Perhatikan bagian <code>startvm</code> dan <code>controlvm</code></p>
<p>Ketika aku enable service tersebut</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo systemctl daemon-reload
</span><span>sudo systemctl enable vm-AdguardHome.service
</span></code></pre>
<p>Terakhir, test reboot komputer kita. Jeng jeng jeng, vm AdguardHome yang ada di dalam virtualbox auto start otomatis.</p>
<p>Cool~</p>
Mendapatkan Full Path File atau Direktori dari Terminal
2020-04-12T19:43:13+07:00
2020-04-12T19:43:13+07:00
Unknown
https://www.sumarsono.com/mendapatkan-full-path-file-atau-direktori-dari-terminal/
<p>Perkenalkan, <a href="https://manpages.debian.org/buster/coreutils/realpath.1.en.html">realpath</a> sebuah utility yang dibawa coreutils dan aku baru tahu. Katrok banget dah pokoknya.
Kadang, kita ini butuh full path dari direktori maupun file untuk kita copas atau kita proses. Selama ini, aku kalau dapetin full path sebuah direktory selalu pakai <code>pwd</code>.
Kemudian kalau butuh full path dari sebuah file, aku selalu pakai cwd dan copas filename yang dimaksud. Kocak kan? It's work tapi kan berasa <code>ngehe</code> banget.</p>
<p>Ketika aku tahu ada command <code>realpath</code>, aku langsung merasa <em>shit</em> selama ini aku bego banget. Selama ini aku pakai cara yang engga efektif. Cara untuk mendapatkan full path dari sebuah file cukup mudah pakai command <code>realpath</code>
Contohnya:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>$ realpath breath2.png
</span><span>
</span><span>/usr/share/backgrounds/breath2.png
</span></code></pre>
<p>Tuh langsung nongol full path file, engga perlu <code>pwd</code> terus append filename-nya, haha.</p>
<p>Itu juga berlaku untuk mendapatkan full path dari sebuah direktori, contohnya:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>$ realpath manjaro-wallpapers-18.0
</span><span>
</span><span>/usr/share/backgrounds/manjaro-wallpapers-18.0
</span></code></pre>
<p>Tuh langsung dapet full path dari direktori</p>
<p>Setelah ini semoga muscle memory-ku terbiasa menggunakan realpath. Sudah dimudahkan kok mempersulit diri.</p>
Ubuntu Touch Mido (Redmi Note 4x)
2020-04-12T11:54:41+07:00
2020-04-12T11:54:41+07:00
Unknown
https://www.sumarsono.com/ubuntu-touch-mido-redmi-note-4x/
<p>Setelah sekian lama, akhirnya ada yang berhasil porting Ubuntu Touch (ubports) ke hp xiaomi redmi note 4x (Mido).
Info detailnya bisa kalian baca di <a href="https://forums.ubports.com/topic/3999/xiaomi-redmi-note-4x-mido">Forum Ubport</a>
dan di <a href="https://forum.xda-developers.com/redmi-note-4/xiaomi-redmi-note-4-snapdragon-roms-kernels-recoveries--other-development/rom-ubuntu-touch-redmi-note-4x-t4069381">XDA developer</a>
Ubuntu Touch ini sejenis sama [Sailfish OS]({% post_url 2019-02-02-upgrade-sailfishos-mido-ke-sipoonkorpi-(3.0.1.11) %}), alternatif os hp selain android.</p>
<p>Penasaran ingin mencicipi, berikut ini langkah-langkah yang aku tempuh hingga berhasil boot Ubuntu Touch:</p>
<ul>
<li>Aku pakai TWRP versi 3.3.1 (Varian OrangeFox R10.1)</li>
<li>Download (simpan di microSD) Ubuntu Touch untuk Mido, <a href="http://www.mediafire.com/file/dj68d53sg0loprz/Ubuntu-Touch-mido%2528Alpha_V1.0%2529.zip/file">klik disini</a>. Untuk link yang up to date silakan ke forum XDA diatas.</li>
<li>Reboot ke TWRP</li>
<li>Format data (Format ya, bukan wipe)</li>
<li>Reboot ke Recovery TWRP lagi</li>
<li>Wipe System, Cache, and Data (nah, kali ini wipe)</li>
<li>Flash Ubuntu Touch yang sudah di download</li>
<li>Reboot ke system (TWRP akan komplain gak ada OS terpasang, abaikan saja)</li>
<li>Jreng-jreng, masuk ke Ubuntu Touch</li>
</ul>
<p>PS: Password default adalah <code>a</code></p>
<p>Setelah mencoba beberapa jam, so pasti ini OS engga bisa ngalahin ekosistem android. Tapi untuk sekedar iseng mengobati penasaran. OKE banget. Melebihi ekspetasiku.
Kalau dibandingkan dengan sailfish OS, lebih sleek sailfishOS sih. Ubuntu Touch menang di browser, yep SailfishOS masih pakai web browser dengan engine kuno yang engga nyaman dipakai dan suka error kalau play youtube.</p>
Kirim File dari Terminal ke Telegram
2020-04-08T13:10:08+07:00
2020-04-08T13:10:08+07:00
Unknown
https://www.sumarsono.com/kirim-file-dari-terminal-ke-telegram/
<p>Lagi remote komputer pakai ssh, pengen kirim file ke telegram? Mudah, begini caranya:</p>
<ol>
<li>Bikin bot di <a href="https://telegram.me/BotFather">BotFather</a> dan catat tokennya.</li>
<li>Chat dengan bot yang barusan dibikin untuk start.</li>
<li>Install telegram send di komputer <code>pip3 install telegram-send</code></li>
<li>Jalankan perintah <code>telegram-send --configure</code></li>
<li>Masukin token bot kita, kemudian ikuti instruksi yang muncul.</li>
<li>Tinggal kirim filenya pakai perintah <code>telegram-send --file doraemon.mkv</code>, maka file doraemon.mkv akan dikirm ke bot kita. Tinggal unduh/share deh.</li>
</ol>
<p>Cool~</p>
Laravel Custom Message-ID Swift Mailer
2020-03-30T15:21:25+07:00
2020-03-30T15:21:25+07:00
Unknown
https://www.sumarsono.com/laravel-custom-message-id-swift-mailer/
<p>Laravel membawa swift mailer untuk fitur kirim email. Satu hal yang ngeselin dari Swift Mailer itu bagian message-ID, dia akan generate <code>message-ID: <random@swift.generated></code>.
Imbasnya ketika melewati rspamd dia akan kena symbol <code>MID_RHS_NOT_FQDN</code>, memang tidak serta merta di flag sebagai spam, tapi cukup kesel aja pas lihat log. Haha.
Solusinya, custom message-ID swift mailer, bagian domainnya yg di custom supaya jadi fqdn. Jadi hasil akhirnya akan berupa message-ID: random@domain.com.</p>
<p>Pertama, edit file <code>config/mail.php</code> tambahin:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>'domain' => 'sumarsono.com',
</span></code></pre>
<p>Kedua, bikin <code>listener</code> baru pakai <code>artisan</code>:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>php artisan make:listener -e 'Illuminate\Mail\Events\MessageSending' MessageSendingListener
</span></code></pre>
<p>Ketiga, edit <code>listener</code> yang tadi dibuat menjadi seperti berikut ini:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span><?php
</span><span>/**
</span><span> * Set the domain part in the message-id generated by Swift Mailer
</span><span> */
</span><span>
</span><span>namespace App\Listeners;
</span><span>
</span><span>use Illuminate\Mail\Events\MessageSending;
</span><span>use Swift_Mime_IdGenerator;
</span><span>
</span><span>class MessageSendingListener
</span><span>{
</span><span> /**
</span><span> * Create the event listener.
</span><span> *
</span><span> * @return void
</span><span> */
</span><span> public function __construct()
</span><span> {
</span><span> //
</span><span> }
</span><span>
</span><span> /**
</span><span> * Handle the event.
</span><span> *
</span><span> * @param MessageSending $event
</span><span> * @return void
</span><span> */
</span><span> public function handle(MessageSending $event)
</span><span> {
</span><span> $event->message->setId((new Swift_Mime_IdGenerator(config('mail.domain')))->generateId());
</span><span> }
</span><span>}
</span></code></pre>
<p>Keempat, daftarkan <code>listener</code> ke <code>app/Providers/EventServiceProvider</code>:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span> protected $listen = [
</span><span>
</span><span> // [...]
</span><span>
</span><span> \Illuminate\Mail\Events\MessageSending::class => [
</span><span> \App\Listeners\MessageSendingListener::class,
</span><span> ],
</span><span> ];
</span></code></pre>
<p>Selesai, coba kirim email maka message-ID sudah berubah menjadi <code>Message-ID: <8f19abc09142878031510fd7cce7dece@sumarsono.com></code> dan rspamd udah gak komplain lagi.</p>
<p>Cool~</p>
Log GNU Screen
2020-03-25T09:09:16+07:00
2020-03-25T09:09:16+07:00
Unknown
https://www.sumarsono.com/log-gnu-screen/
<p>Aku biasa memakai gnu <code>screen</code> ketika ingin menjaga session di remote shell.
Misalnya ketika aku jalanin bash script yang memakan waktu cukup lama dan script tersebut akan mati ketika ssh session terputus. Untuk menjaga agar session tidak terputus dan script tetap jalan walaupun koneksi ssh putus, maka aku memakai <code>screen</code>. Biasanya aku run <code>screen</code> dengan nama, biar mudah ketika di list dan dipanggil kembali.</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>screen -S anuan
</span></code></pre>
<p>Artinya, aku menjalankan <code>screen</code> dengan nama sesi <code>anuan</code>. Kalau kita jalanin <code>screen -list</code> akan muncul:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>There is a screen on:
</span><span> 2406.anuan (Detached)
</span><span>1 Socket in /run/screens/S-sysadmin.
</span></code></pre>
<p>GNU <code>screen</code> ini kan terminal multiplexer dan punya scroll buffer sendiri, bermasalah ketika stdout sangat panjang dan kita ingin baca dari titik awal.
Sudah pasti stdout akan terpotong.</p>
<p>Nah, untuk memudahkan kita membaca stdout yg sangat panjang, <code>screen</code> membawa fitur log. Cukup kasih parameter <code>-L</code></p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>screen -L -S anuan
</span></code></pre>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>-L Turn on output logging.
</span><span>-S sockname Name this session <pid>.sockname instead of <pid>.<tty>.<host>.
</span></code></pre>
<p>Selesai, dengan begitu <code>screen</code> akan menyimpan log di current directory dengan nama <code>screenlog.#</code>. <code>#</code> disini angka dimulai dari 0.</p>
<p>Oh iya lupa, ngejelasin GNU screen itu apa? Dikutip dari <a href="https://www.gnu.org/software/screen/">gnu.org</a>:</p>
<blockquote>
</blockquote>
<p>Screen is a full-screen window manager that multiplexes a physical terminal between several processes, typically interactive shells. Each virtual terminal provides the functions of the DEC VT100 terminal and, in addition, several control functions from the ANSI X3.64 (ISO 6429) and ISO 2022 standards (e.g., insert/delete line and support for multiple character sets). There is a scrollback history buffer for each virtual terminal and a copy-and-paste mechanism that allows the user to move text regions between windows. When screen is called, it creates a single window with a shell in it (or the specified command) and then gets out of your way so that you can use the program as you normally would. Then, at any time, you can create new (full-screen) windows with other programs in them (including more shells), kill the current window, view a list of the active windows, turn output logging on and off, copy text between windows, view the scrollback history, switch between windows, etc. All windows run their programs completely independent of each other. Programs continue to run when their window is currently not visible and even when the whole screen session is detached from the users terminal.</p>
Memisahkan Environment Vuejs
2020-03-20T18:56:51+07:00
2020-03-20T18:56:51+07:00
Unknown
https://www.sumarsono.com/memisahkan-environment-vuejs/
<p>Aku ada sebuah project yang dibuat menggunakan VueJs. Project ini akan dideploy dalam tiga environment:</p>
<ul>
<li>Develop</li>
<li>Staging</li>
<li>Production</li>
</ul>
<p>Untuk memudahkan itu, akan aku gunakan docker. Idenya sederhana, yaitu build docker image dengan tag sesuai environmentnya:</p>
<ul>
<li>sianu/myapp:v1-develop</li>
<li>sianu/myapp:v1-staging</li>
<li>sianu/myapp:v1-production</li>
</ul>
<p>Kenapa harus dipisah?. Hal itu disebabkan oleh API yang dipisah juga. Untuk setiap environment akan hit API yang berbeda:</p>
<ul>
<li>Develop akan hit develop.sianu.com/api</li>
<li>Staging akan hit staging.sianu.com/api</li>
<li>Production akan hit production.sianu.com/api</li>
</ul>
<p>Jika tidak dipisah, akan repot ngatur .env vuejs. Untungnya, vuejs memberi fasilitasi untuk hal begini. Si vue ini enak ngatur .env-nya. Jadi cukup bikin tiga file environment untuk app sianu:</p>
<ul>
<li>.env.develop</li>
<li>.env.staging</li>
<li>.env.production</li>
</ul>
<p>Masing-masing .env disii URI api yang sesuai. Dengan begitu, kita tinggal pass parameter ke command <code>npm run build</code>. Jadi untuk build masing-masing env adalah:</p>
<p>Build vue js dalm environment develop:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>npm run build -- --mode develop
</span></code></pre>
<p>Build vue js dalm environment staging:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>npm run build -- --mode staging
</span></code></pre>
<p>Build vue js dalm environment production:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>npm run build -- --mode production
</span></code></pre>
<p>Setelah itu, aku siapkan Dockerfile untuk setiap environment:</p>
<ul>
<li>Dockerfile-develop</li>
<li>Dockerfile-staging</li>
<li>Dockerfile-production</li>
</ul>
<p>Isi dari Dockerfile-develop</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>FROM node:lts-alpine as build-stage
</span><span>WORKDIR /app
</span><span>COPY package*.json ./
</span><span>RUN npm install
</span><span>COPY . .
</span><span>RUN npm run build -- --mode develop
</span><span>
</span><span>FROM nginx:stable-alpine as production-stage
</span><span>RUN apk --update --no-cache add curl
</span><span>COPY nginx.conf /etc/nginx/conf.d/default.conf
</span><span>COPY --from=build-stage /app/dist /usr/share/nginx/html
</span><span>HEALTHCHECK --interval=30s --timeout=3s CMD curl -f http://localhost/ || exit 1
</span><span>EXPOSE 80
</span><span>CMD ["nginx", "-g", "daemon off;"]
</span></code></pre>
<p>Isi dari Dockerfile-staging</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>FROM node:lts-alpine as build-stage
</span><span>WORKDIR /app
</span><span>COPY package*.json ./
</span><span>RUN npm install
</span><span>COPY . .
</span><span>RUN npm run build -- --mode staging
</span><span>
</span><span>FROM nginx:stable-alpine as production-stage
</span><span>RUN apk --update --no-cache add curl
</span><span>COPY nginx.conf /etc/nginx/conf.d/default.conf
</span><span>COPY --from=build-stage /app/dist /usr/share/nginx/html
</span><span>HEALTHCHECK --interval=30s --timeout=3s CMD curl -f http://localhost/ || exit 1
</span><span>EXPOSE 80
</span><span>CMD ["nginx", "-g", "daemon off;"]
</span></code></pre>
<p>Isi dari Dockerfile-production</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>FROM node:lts-alpine as build-stage
</span><span>WORKDIR /app
</span><span>COPY package*.json ./
</span><span>RUN npm install
</span><span>COPY . .
</span><span>RUN npm run build -- --mode production
</span><span>
</span><span>FROM nginx:stable-alpine as production-stage
</span><span>RUN apk --update --no-cache add curl
</span><span>COPY nginx.conf /etc/nginx/conf.d/default.conf
</span><span>COPY --from=build-stage /app/dist /usr/share/nginx/html
</span><span>HEALTHCHECK --interval=30s --timeout=3s CMD curl -f http://localhost/ || exit 1
</span><span>EXPOSE 80
</span><span>CMD ["nginx", "-g", "daemon off;"]
</span></code></pre>
<p>Untuk build docker image masing-masing environment:</p>
<p>Build docker image dengan environment develop:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>docker build -t registry.private.com/sianu/myapp:v1-develop -f Dockerfile-develop .
</span></code></pre>
<p>Build docker image dengan environment staging:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>docker build -t registry.private.com/sianu/myapp:v1-staging -f Dockerfile-staging .
</span></code></pre>
<p>Build docker image dengan environment production:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>docker build -t registry.private.com/sianu/myapp:v1-production -f Dockerfile-production .
</span></code></pre>
<p>Selesai, sekarang aku punya tiga docker image app vuejs dengan environment yg berbeda-beda.</p>
<p>Cool~</p>
Wireless Card RTL8723DE in Manjaro Linux
2020-03-20T18:26:19+07:00
2020-03-20T18:26:19+07:00
Unknown
https://www.sumarsono.com/wireless-card-rtl8723de-in-manjaro-linux/
<p>Artikel ini menceritakan bagaimana aku mengatasi Wifi RTL8723DE tidak bisa nyala di distro linux Manjaro.
Semua berawal ketika kantor membolehkan untuk kerja secara remote demi ikut serta dalam pencegahan penyebaran virus korona. Aku termasuk salah satu yang mengajukan kerja secara remote. Untuk mendukung pekerjaan, aku mengajukan satu buah laptop, satu buah modem 4G, dan satu buah simcard untuk internet.</p>
<p>Ketika barang yang kuajukan datang, aku langsung bertanya:</p>
<ul>
<li>OS laptop pakai apa?</li>
<li>Boleh ku install distro linux?</li>
</ul>
<p>OS bawaan laptop adalah Winten. Aku diijinkan untuk reinstall OS-nya, babat habis juga engga masalah.
Itu sebabnya aku install Manajaro KDE ke laptop ini. Selesai install, semua berjalan <del>mulus tanpa</del> dengan kendala. Satu masalah yang sangat krusial, wifi laptopnya engga mau nyala. Tapi bluetooth-nya nyala, padahal wifi+bluetooth satu modul.Berikut ini adalah langkah yang kutempuh untuk mengatasi masalah wifi di manjaro yang tidak mau nyala:</p>
<p>Pertama, cari info modul wifi yang terpasang dengan <code>hwinfo</code>.</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sysadmin@laptop-kantor ~]$ hwinfo --netcard --wlan
</span><span>06: PCI 300.0: 0282 WLAN controller
</span><span> [Created at pci.386]
</span><span> Unique ID: S6TQ.ssFGCi855d4
</span><span> Parent ID: Rtk9.4DPZZRpai56
</span><span> SysFS ID: /devices/pci0000:00/0000:00:02.4/0000:03:00.0
</span><span> SysFS BusID: 0000:03:00.0
</span><span> Hardware Class: network
</span><span> Device Name: "Realtek RTL8723DE 802.11 bgn 1x1 WiFi + BT 4.2 Combo Adapter"
</span><span> Model: "Realtek RTL8723DE 802.11b/g/n PCIe Adapter"
</span><span> Vendor: pci 0x10ec "Realtek Semiconductor Co., Ltd."
</span><span> Device: pci 0xd723 "RTL8723DE 802.11b/g/n PCIe Adapter"
</span><span> SubVendor: pci 0x103c "Hewlett-Packard Company"
</span><span> SubDevice: pci 0x8319
</span><span>
</span></code></pre>
<p>Dari situ kelihatan nih laptop pakai modul wifi RTL8723DE.</p>
<p>Kedua, cari info masalah RTL8723DE di linux, embah google tahu. Akhirnya ketemu satu repo di github <a href="https://github.com/lwfinger/rtlwifi_new.git">lwfinger/rtlwifi_new</a></p>
<p>Ketiga, install driver RTL8723DE di Manjaro.</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>git clone https://github.com/lwfinger/rtlwifi_new.git -b extended
</span><span>cd rtlwifi_new/
</span><span>make
</span><span>sudo make install
</span><span>sudo modprobe -r rtl8723de
</span><span>sudo modprobe rtl8723de
</span></code></pre>
<p>Keempat, tes udah nyala atau belum,</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>DEVICE=$(iw dev | grep Interface | cut -d " " -f2)
</span><span>sudo iw dev $DEVICE scan | egrep "SSID|signal|\(on"
</span><span>BSS d0:ef:c1:3c:84:a0(on wlo1)
</span><span> signal: -41.00 dBm
</span><span> SSID: KOS MUTYA
</span><span>BSS 0c:80:63:3d:d4:e2(on wlo1)
</span><span> signal: -76.00 dBm
</span><span> SSID: KOS MUTYA2
</span><span>BSS 40:7d:0f:69:fe:60(on wlo1)
</span><span> signal: -79.00 dBm
</span><span> SSID: JULIANTI
</span><span>BSS f8:75:88:f4:35:10(on wlo1)
</span><span> signal: -89.00 dBm
</span><span> SSID: HUAWEI-SXPs
</span><span>BSS bc:3f:8f:c7:5c:98(on wlo1)
</span><span> signal: -85.00 dBm
</span><span> SSID: ANAK RANTAU
</span></code></pre>
<p>Sip udah nyala. Masalah selesai. Sampai sekarang, Manjaraku berjalan lancar.</p>
Dilema Work From Home akibat Corona Virus
2020-03-16T12:46:21+07:00
2020-03-16T12:46:21+07:00
Unknown
https://www.sumarsono.com/dilema-work-from-home-akibat-corona-virus/
<p>Ini dilema yang ada di benakku, sangat mengganjal. Aku tulis aja biar aga legaan. Ada banyak hal yang terbayang dalam benakku. Soal WFH. Work from home, aku sebut wfh aja biar singkat. Jika seandainya kantor nerapin aturan wfh karena virus corona, maka inilah dilema yang kupikirkan.</p>
<p>Dilema pertama, <strong>pulang ke rumah atau tetap tinggal di kost?</strong> Pengennya sih pulang ke rumah tapi aku kepikiran dengan orang rumah. Bagaimana jika ternyata pas perjalanan pulang aku terpapar virus corona di transportasi umum. Sampai rumah sudah pasti aku akan menulari mereka. Orang rumah justru lebih rentan karena isinya orang tua dan anak kecil. Lebih dari itu di kampung, fasilitas kesehatan kurang memadai. Puskemas jauh. Rumah sakit lebih jauh. Pilihan terbaik adalah engga pulang, aku sayang mereka. Jadi aku gak mau bawa virus ke mereka.</p>
<p>Dilema kedua <strong>kenyamanan</strong>, sudah pasti kerja dari rumah/kost engga nyaman. Gak ada AC, gak ada kursi yang empuk, gk ada meja yang cocok buat kerja. Pas siang hari sudah serasa di dalam sauna, panas. Aku gak punya working space di dalam rumah/kost.</p>
<p>Dilema ketiga, <strong>fokus kerja</strong>, aku sangat yakin akan susah untuk fokus jika kerja dari rumah/kost. Distraksinya sangat banyak. Mulai dari benda hidup, benda mati, kasat mata, dan tak kasat mata. Orang-orang disekitar akan sulit untuk dijelasin bahwa kita itu kerja dari jam 08.00 - 16.00, walaupun sedang di rumah/kost. Pasti ada aja gangguannya. Ditambah lagi distraksi dari diri sendiri.</p>
<p>Dilema keempat, <strong>komunikasi</strong>, tatap muka aja masih sering <em>miss</em> komunikasi. Apalagi jarak jauh.</p>
<p>Dilema kelima, <strong>administrasi</strong>, apakah kantor secara sistematis sudah siap dengan wfh? Aku tidak bisa menjawabnya. Bagi pemain baru untuk urusan manajemen kerja remote ini gak segampang kerja onsite. Butuh banyak penyesuaian.</p>
<p>Btw, sysadmin itu lahir sudah membawa mindset kerja remote. Daily life sysadmin ya remote <code>ssh</code>, kecuali ada masalah tertentu yang mengharuskan onsite, misalnya maintain hardware.</p>
<p>Itu sedikit unek-unek, haha. Semoga pandemik ini segera berakhir.</p>
<p>Not cool~</p>
Males Masukin Kredensial Mysql
2020-03-16T10:51:05+07:00
2020-03-16T10:51:05+07:00
Unknown
https://www.sumarsono.com/males-masukin-kredensial-mysql/
<p>Aku males masukin kredensial mysql ketika eksekusi perintah terkait mysql. Jadi aku simpan aja kredensialnya di <code>~/.my.cnf</code>. Jangan dicontoh, terutama untuk yang parno soal security.
Aku lakukan ini krn mesin lokal, bukan server produksi.</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>nano ~/.my.cnf
</span></code></pre>
<p>Isinya</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>[client]
</span><span>user=mysqluser
</span><span>password=mysqlpass
</span></code></pre>
<p>Biar cuma userku yg bisa akses tuh file:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>chmod 0600 ~/.my.cnf
</span></code></pre>
<p>Sekarang, setiap aku jalanin <code>mysql</code>, <code>mysqldump</code>, dll langsung nyelonong tanpa perlu input username dan password mysql.</p>
<p>Not cool~</p>
Cara include environment variable kedalam cURL
2020-02-25T10:51:18+07:00
2020-02-25T10:51:18+07:00
Unknown
https://www.sumarsono.com/cara-include-environment-variable-kedalam-curl/
<p>Aku ingin script <code>curl</code> membaca environment variable untuk body datanya, eh error. Ternyata solusinya sangat mudah. Scriptku kira-kira begini:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>API_KEY="mykey"
</span><span>DOMAIN_NAME="mydomain.com"
</span><span>
</span><span>SUBDOMAIN_NAME="$1"
</span><span>IP_ADDRESS="192.168.1.1"
</span><span>
</span><span>curl -X POST -H "Content-Type: application/json" \
</span><span> -H "X-Api-Key: $API_KEY" \
</span><span> -d '{"rrset_name": "$SUBDOMAIN_NAME",
</span><span> "rrset_type": "A",
</span><span> "rrset_ttl": 1800,
</span><span> "rrset_values": ["$IP_ADDRESS"]}' \
</span><span> https://otherdomain.com/api/v99/domains/$DOMAIN_NAME/records
</span></code></pre>
<p>Ketika di eksekusi error, data rrset_name gak sesuai. Nah disini yang jadi masalah adalah <code>'</code>, apapun yg diapit oleh <code>'</code> akan dieksekusi apa adanya. Contoh diatas adalah</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>-d '{"rrset_name": "$SUBDOMAIN_NAME",
</span><span> "rrset_type": "A",
</span><span> "rrset_ttl": 1800,
</span><span> "rrset_values": ["$IP_ADDRESS"]}'
</span></code></pre>
<p>"$SUBDOMAIN_NAME" akan terkirim apa adanya $SUBDOMAIN_NAME bukan digantikan oleh $1.</p>
<p>Solusi dari masalah yang kuhadapi adalah sebagai berikut:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>API_KEY="mykey"
</span><span>DOMAIN_NAME="mydomain.com"
</span><span>
</span><span>SUBDOMAIN_NAME="$1"
</span><span>IP_ADDRESS="192.168.1.1"
</span><span>
</span><span>curl -X POST -H "Content-Type: application/json" \
</span><span> -H "X-Api-Key: $API_KEY" \
</span><span> -d '{"rrset_name": "'"$SUBDOMAIN_NAME"'",
</span><span> "rrset_type": "A",
</span><span> "rrset_ttl": 1800,
</span><span> "rrset_values": ["'"$IP_ADDRESS"'"]}' \
</span><span> https://otherdomain.com/api/v99/domains/$DOMAIN_NAME/records
</span></code></pre>
<p><code>"'"$SUBDOMAIN_NAME"'"</code> dan <code>"'"$IP_ADDRESS"'"</code></p>
<p>Cara ini mungkin kurang elegan, tapi it's just work.</p>
<p>Sumber solusi: <a href="https://superuser.com/questions/835587/how-to-include-environment-variable-in-bash-line-curl">superuser.com</a>.</p>
Gamepad Terios X3 Linux
2020-02-24T16:49:22+07:00
2020-02-24T16:49:22+07:00
Unknown
https://www.sumarsono.com/gamepad-terios-x3-linux/
<p>Pada [artikel sebelumnya]({% post_url 2020-02-24-gamepad-terios-x3-mode-usb %}) aku sudah menulis bagaimana cara menggunakan gamepad terios x3 mode usb tanpa bluetooth. Pada artikel ini akan aku tulis bagaimana cara pakai terios x3 mode bluetooth di linux. Aku pakai distro manjaro, distro lain silakan menyesuaikan. Terios x3 di Manjaro sebenarnya plug and play, begitu terhubung dengan bluetooth maka bisa dipakai, terdeteksi di setting <code>Game Controller</code>. Tapi, ketika di aplikasi PPSSPP, tombol dpad tidak berfungsi. Jadi perlu langkah tambahan. Berikut ini cara yang ku tempuh sampai akhirnya bisa kupakai di PPSSPP.</p>
<p>Pertama, install packages yang dibutuhkan:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo pacman -S bluez-plugins bluez-utils
</span></code></pre>
<p>Package bluez sudah ada saat install manjaro, jadi aku hanya butuh plugin dan utils-nya.</p>
<p>Berikutnya, aku install package <code>xboxdrv</code> dari AUR. <code>xboxdrv </code>merupakan userspace driver untuk gampepad</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>yay -S xboxdrv
</span></code></pre>
<p>Selanjutnya, aku bikin udev rule </p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo nano /etc/udev/rules.d/99-btjoy.rules
</span><span>
</span><span># isinya:
</span><span>ACTION=="add", SUBSYSTEM=="input", ATTRS{name}=="Gamepad", ATTRS{uniq}=="66:36:28:80:63:25", SYMLINK+="btjoy"
</span></code></pre>
<p>"Gamepad" itu sesuai dengan nama di App Bluez dan "66:36:28:80:63:25" merupakan address bluetooth terios x3 punyaku yang aku dapatkan dari app bluez.</p>
<p>Selanjutnya, aku bikin konfigurasi <code>xboxdrv</code></p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>nano ~/.config/xboxdrv/ipega.conf
</span><span>
</span><span># isinya:
</span><span>#iPEGA PG-9068 and PG-9087 Config
</span><span>
</span><span>[xboxdrv]
</span><span>evdev-debug = true
</span><span>evdev-grab = true
</span><span>rumble = false
</span><span>mimic-xpad = true
</span><span>
</span><span>[evdev-absmap]
</span><span>ABS_HAT0X = dpad_x
</span><span>ABS_HAT0Y = dpad_y
</span><span>
</span><span>ABS_X = X1
</span><span>ABS_Y = Y1
</span><span>
</span><span>ABS_Z = X2
</span><span>ABS_RZ = Y2
</span><span>
</span><span>[axismap]
</span><span>-Y1 = Y1
</span><span>-Y2 = Y2
</span><span>
</span><span>[evdev-keymap]
</span><span>BTN_A=a
</span><span>BTN_B=b
</span><span>BTN_Y=y
</span><span>BTN_X=x
</span><span>BTN_TR=rb
</span><span>BTN_TL=lb
</span><span>BTN_TR2=rt
</span><span>BTN_TL2=lt
</span><span>BTN_THUMBL=tl
</span><span>BTN_THUMBR=tr
</span><span>BTN_START=start
</span><span>BTN_SELECT=back
</span><span>
</span><span>BTN_MODE = guide
</span></code></pre>
<p>Sudah selesai, kalau gamepad terios x3 sudah terhubung ke pc via bluetooh (lampu indikator 1 menyala), kita tinggal jalankan perintah</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo xboxdrv --evdev /dev/btjoy --config ~/.config/xboxdrv/ipega.conf
</span></code></pre>
<p>Outpunya begini:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>xboxdrv 0.8.8 - http://pingus.seul.org/~grumbel/xboxdrv/
</span><span>Copyright © 2008-2011 Ingo Ruhnke <grumbel@gmail.com>
</span><span>Licensed under GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
</span><span>This program comes with ABSOLUTELY NO WARRANTY.
</span><span>This is free software, and you are welcome to redistribute it under certain conditions; see the file COPYING for details.
</span><span>
</span><span>
</span><span>Your Xbox/Xbox360 controller should now be available as:
</span><span> /dev/input/js1
</span><span> /dev/input/event20
</span><span>
</span><span>Press Ctrl-C to quit, use '--silent' to suppress the event output
</span></code></pre>
<p>Gamepad terios x3 sudah bisa dipakai di linux, tinggal buka aplikasi PPSSPP kemudian setting controller untuk mapping.</p>
<p>Cool~</p>
<p>Sumber referensi: <a href="https://wiki.archlinux.org/index.php/Gamepad#iPEGA-9017s_and_other_Bluetooth_gamepads">arch linux wiki</a></p>
Gamepad Terios X3 Mode USB
2020-02-24T08:19:42+07:00
2020-02-24T08:19:42+07:00
Unknown
https://www.sumarsono.com/gamepad-terios-x3-mode-usb/
<p>Kira-kira setengah tahun yang lalu, aku membeli sebuah gamepad murah meriah yang dilabeli "Terios X3 Bluetooth Wireless Gamepad for Smartphone". Tujuan awal beli adalah untuk main game psp di HP Android pakai emulator ppsspp. Gamepad ini langsung bisa dipakai begitu terhubung dengan dengan bluetooth HP. Jika gamepad ini bisa dipakai melalui koneksi bluetooth, apakah bisa juga dipakai dengan koneksi kabel usb? Untuk PC yang gak ada bluetoothnya tentu akan sangat berguna.</p>
<p>Penggunaan gamepad terios x3 dengan kabel usb, tidak tertulis di buku manualnya. Di buku manualnya hanya tertera cara pakai menggunakan bluetooth. Ketika gamepad dihubungkan ke PC, ia hanya mode charging, tidak terdeteksi apapun di <code>lsusb</code>. Mungkin, ada kombo yang harus ditekan sama halnya dengan ketika menggunakan koneksi bluetooth.</p>
<p>Ternyata cara menggunakan mode usb terios x3 sangat mudah.</p>
<ul>
<li>Lepas kabel usb gamepad terios x3.</li>
<li>Tekan dan tahan tombol R1 + Home, hingga lampu 1 dan 4 kedip-kedip, lepaskan.</li>
<li>Colok kabel USB dari PC ke gamepad terios x3, ditunggu sebentar maka akan menyala lampu nomer 2.</li>
</ul>
<p>Ketika lampu nomer 2 menyala, cek <code>lsusb</code> maka gamepad akan terbaca:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>Bus 002 Device 008: ID 2563:0575 ShanWan PC/PS3/Android Gamepad
</span></code></pre>
<p>Sampai disini coba buka <code>gamepad configuration</code> di Settings, test tombolnya, sudah bisa dipakai. Tapi ketika di coba di PPSSPP untuk PC, tombol dpad tidak berfungsi padahal di <code>gamepad configuration</code> tombol dpad jalan normal. </p>
<p>Nah ternyata ada satu mode lagi yang support PPSSPP di PC, mode xbox. Caranya yaitu ketika lampu nomer 2 menyala, tekan dan tahan tombol Home sampai lampu yang menyala pindah ke nomer 4. Ketika lampu nomer 4 menyala dan kita cek <code>lsusb</code>, maka akan terdeteksi:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>Bus 002 Device 010: ID 045e:028e Microsoft Corp. Xbox360 Controller
</span></code></pre>
<p>Test di ppsspp gamepad terios x3 mode xbox sudah bisa dipakai, semua button berfungsi termasuk dpadnya. Akhirnya gamepad terios x3 yang kubeli bisa kupakai di HP pakai bluutooth dan di PC pakai kabel USB. Lumayan gamepad murmer jadi serbaguna.</p>
<p>Cool~</p>
Ubuntu server 18.04 static ip address
2020-02-19T08:05:28+07:00
2020-02-19T08:05:28+07:00
Unknown
https://www.sumarsono.com/ubuntu-server-18-04-static-ip-address/
<p>Static ip address kita butuhkan supaya kita tidak selalu cek ip address ketika kita hendak konek ke server.
Ubuntu server 18.04 menggunakan netplan untuk konfigurasi networknya. Oleh sebab itu, jika kita ingin set static ip address di ubuntu 18.04, kita harus set pakai netplan. Dalam hal ini aku akan set static ip address ubuntu 18.04 di raspberry pi 3.</p>
<p>Caranya cukup mudah:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo nano /etc/netplan/50-cloud-init.yaml
</span></code></pre>
<p>Konfigurasinya kurang lebih seperti ini:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>network:
</span><span> ethernets:
</span><span> eth0:
</span><span> dhcp4: no
</span><span> addresses:
</span><span> - 192.168.1.176/24
</span><span> gateway4: 192.168.1.168
</span><span> nameservers:
</span><span> addresses: [9.9.9.9, 1.1.1.1]
</span><span> #optional: true
</span><span> version: 2
</span></code></pre>
<p>Tinggal kita apply</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo netplan apply
</span></code></pre>
<p>Sudah selesai, ip address ubuntu server 18.04 di raspberry pi ku akan selalu pakai 192.168.1.176</p>
Install Pi-hole dan Dnscrypt proxy di Raspberry Pi 3
2020-02-17T14:12:46+07:00
2020-02-17T14:12:46+07:00
Unknown
https://www.sumarsono.com/install-pi-hole-dan-dnscrypt-proxy-di-raspberry-pi-3/
<p>Menggabungkan ads blocker <a href="https://pi-hole.net/">pihole</a> dengan <a href="https://github.com/DNSCrypt/dnscrypt-proxy">dnscrypt proxy</a> merupakan sesuatu yang menarik. Untuk install pihole dan dnscrypt di Raspberry Pi 3 juga sangat mudah.
Yang harus diperhatikan adalah pihole dan dnscrypt sama-sama menggunakan port 53 secara default. Oleh sebab itu, salah satu harus mengalah dan menggunakan port selain 53.
Ide menggabungkan pihole dengan dnscrypt proxy sangat sederhana, yakni kita jadikan dnscrypt proxy sebagai upstream untuk pihole. Hal ini menjadi mungkin karena pihole versi terbaru sudah mendukung custom port untuk upstream dns-nya. Dan dnscrypt proxy juga bisa jalan di port selain port 53.</p>
<p>Untuk install pihole dan dnscrypt di raspberry pi 3, pertama aku install pihole terlebih dahulu.</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>curl -sSL https://install.pi-hole.net | bash
</span></code></pre>
<p>Btw itu bukan best practice ya, jangan biasakan run random stuff from internet di terminal. Aku sarankan untuk download script installernya, kemudian dibaca. Supaya benar-benar tahu apa yang dilakukan oleh script tersebut.</p>
<p>Berikutnya, aku install dnscrypt proxy</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>cd /opt
</span><span>
</span><span># download latest release, aku pakai ubuntu 18.04
</span><span># jadi aku milih yang arm 64
</span><span># silakan disesuaikan dgn os masing2
</span><span>sudo wget https://github.com/DNSCrypt/dnscrypt-proxy/releases/download/2.0.39/dnscrypt-proxy-linux_arm64-2.0.39.tar.gz
</span><span>
</span><span>sudo tar -xf dnscrypt-proxy-linux_arm64-2.0.39.tar.gz
</span><span>sudo mv linux-arm64 dnscrypt-proxy
</span><span>sudo cd dnscrypt-proxy
</span><span>sudo cp example-dnscrypt-proxy.toml dnscrypt-proxy.toml
</span><span>
</span><span># aku ubah port 53 menjadi 54
</span><span># supaya tidak bentrok antara dnscrypt dengan pihole
</span><span>sudo nano dnscrypt-proxy.toml
</span><span>
</span><span>sudo ./dnscrypt-proxy -service install
</span><span>sudo ./dnscrypt-proxy -service start
</span></code></pre>
<p>Langkah terakhir, aku ubah upstream dns pihole ke dnscrypt proxy
<img src="/assets/images/pihole-setting.webp" alt="Pihole Dnscrypt proxy" /></p>
<p>Selesai.</p>
Setup Pihole sebagai Local DNS server
2020-02-17T09:28:41+07:00
2020-02-17T09:28:41+07:00
Unknown
https://www.sumarsono.com/setup-pihole-sebagai-local-dns-server/
<p>Tujuannya untuk membuat local resolver, sama seperti artikel [ini]({% post_url 2019-11-05-cara-mudah-bikin-dns-server-lokal-pakai-coredns %}).
Disini engga pakai Coredns karena kebetulan mau dijadiin satu aja sama pihole. Biar gak repot konfig, jadi ikut config dns si pihole aja. Goal yang ingin dicapai sederhana, ketika Budi ketik <code>sysadmin-pc.lan</code> di address bar browser, maka akan tampil web yg di host di sysadmin-pc.
Ya biar gak hafalan IP, memudahkan temen-temen.</p>
<p>Sangat sederhana untuk mencapai itu di pi-hole, pertama kita bikin konfigurasi dnsmasq:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>echo "addn-hosts=/etc/pihole/lan.list" | sudo tee /etc/dnsmasq.d/02-lan.conf
</span></code></pre>
<p>kedua, bikin <code>/etc/pihole/lan.list</code>:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo nano /etc/pihole/lan.list
</span></code></pre>
<p>Contoh isi seperti ini:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>#ipaddress fqdn hostname
</span><span>192.168.1.26 sysadmin-pc.lan sysadmin-pc
</span></code></pre>
<p>Terakhir, restart dns service pihole</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo pihole restartdns
</span></code></pre>
<p>Selesai. Untuk semua pc yang menggunakan pihole sbg dns servernya, dapat mengakses http://sysadmin-pc.lan dari browser.
<img src="/assets/images/sysadmin-pc.lan.webp" alt="sysadmin-pc.lan" /></p>
<p>Cool~</p>
Raspberry Pi 3b 64 bit OS pakai Ubuntu Server 18.04
2020-02-13T16:36:29+07:00
2020-02-13T16:36:29+07:00
Unknown
https://www.sumarsono.com/raspberry-pi-3b-64-bit-os-pakai-ubuntu-server-18-04/
<p>OS official untuk raspberry pi 3b adalah raspbian. Sampai artikel ini ditulis, raspbian masih menggunakan varian 32 bit. Padahal, hardware raspberry pi 3b mendukung 64 bit. Beberapa software jaman sekarang juga hanya menyediakan varian 64 bit saja. Contohnya docker, untuk dapat menjalankan docker kita butuh OS 64 bit. Jika kita membutuhkan OS 64 bit untuk raspberry pi 3b, maka kita harus mencari OS selain raspbian. Untungnya, sekarang ubuntu mengeluarkan Ubuntu server untuk raspberry pi 3b dan kita bisa memilih 32 bit atau 64 bit. Detailnya klik link berikut <a href="https://ubuntu.com/download/raspberry-pi">Install Ubuntu Server on a Raspberry Pi 2, 3 or 4</a>.</p>
<p>Cara installnya cukup mudah, berikut ini adalah cara install Ubuntu server 18.04 untuk raspberry pi 3b:</p>
<ul>
<li>Download Ubuntu server 18.04 untuk raspberry pi 3b</li>
<li>Pasang micro sd ke PC</li>
<li>Burn image Ubuntu server 18.04 untuk raspberry pi 3b ke micro sd menggunakan bantuan <a href="https://www.balena.io/etcher/">Balena Etcher</a></li>
<li>Selesai, tinggal pasang micro sd ke raspberry pi 3b. Oh iya, untuk mengaktifkan ssh setelah fresh install, sebelum memasang ke raspberry pi jangan lupa buat file bernama <code>ssh</code> di partisi boot di micro sd tadi.</li>
</ul>
<p>Setelah selesai install, tinggal ssh ke raspberry pi pakai username <code>ubuntu</code> dan password <code>ubuntu</code></p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>➜ ~ ssh ubuntu@192.168.1.176
</span><span>ubuntu@192.168.1.176's password:
</span><span>Welcome to Ubuntu 18.04.4 LTS (GNU/Linux 5.3.0-1017-raspi2 aarch64)
</span><span>
</span><span> * Documentation: https://help.ubuntu.com
</span><span> * Management: https://landscape.canonical.com
</span><span> * Support: https://ubuntu.com/advantage
</span><span>
</span><span> System information as of Thu Feb 13 09:48:29 UTC 2020
</span><span>
</span><span> System load: 0.0 Processes: 110
</span><span> Usage of /: 10.5% of 14.44GB Users logged in: 0
</span><span> Memory usage: 26% IP address for eth0: 192.168.1.176
</span><span> Swap usage: 0%
</span><span>
</span><span>
</span><span>0 packages can be updated.
</span><span>0 updates are security updates.
</span><span>
</span><span>Your Hardware Enablement Stack (HWE) is supported until April 2023.
</span><span>
</span><span>Last login: Thu Feb 13 09:31:20 2020 from 192.168.1.26
</span><span>ubuntu@ubuntu:~$
</span></code></pre>
<p>Cara mencari tahu ip address raspberry pi, aku pakai nmap</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo nmap -sn 192.168.1.0/24
</span></code></pre>
<p><code>192.168.1.0/24</code> itu range ip dari router yang kupakai.</p>
<p>Hasilnya, cari yang ada kata Raspbeeery Pi Foundation</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>...
</span><span>Nmap scan report for 192.168.1.176
</span><span>Host is up (0.00028s latency).
</span><span>MAC Address: B8:27:EB:8A:EB:C0 (Raspberry Pi Foundation)
</span><span>...
</span></code></pre>
<p>Selesai, akhirnya raspberry pi 3b pakai os 64 bit. Dan bisa pasang docker, tentunya.</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>ubuntu@ubuntu:~$ screenfetch -n
</span><span> ubuntu@ubuntu
</span><span> OS: Ubuntu 18.04 bionic
</span><span> Kernel: aarch64 Linux 5.3.0-1017-raspi2
</span><span> Uptime: 24m
</span><span> Packages: 507
</span><span> Shell: bash 4.4.20
</span><span> CPU: BCM2835 @ 4x 1.2GHz [53.1°C]
</span><span> GPU: simple
</span><span>BCM2708
</span><span> RAM: 152MiB / 906MiB
</span></code></pre>
<p>Cool~</p>
Kubernetes diatas LXC
2020-01-20T15:24:40+07:00
2020-01-20T15:24:40+07:00
Unknown
https://www.sumarsono.com/kubernetes-diatas-lxc/
<h1 id="kubernetes-on-lxc-lxd">Kubernetes on lxc/lxd</h1>
<p>Tulisan ini berisi catatan cara aku setup kubernetes diatas lxd/lxc.
Catatan ini hanya akan setup 1 master dan 1 worker.</p>
<p>Host Info:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>➜ ~ inxi -b
</span><span>System: Host: sysadmin-pc Kernel: 5.4.12-1-MANJARO x86_64 bits: 64 Desktop: KDE Plasma 5.17.5 Distro: Manjaro Linux
</span><span>Machine: Type: Desktop Mobo: ECS model: H81H3-M4 v: 1.0 serial: <root required> UEFI: American Megatrends v: 4.6.5
</span><span> date: 05/21/2015
</span><span>CPU: Dual Core: Intel Core i3-4160 type: MT MCP speed: 1439 MHz min/max: 800/3600 MHz
</span><span>Graphics: Device-1: Intel 4th Generation Core Processor Family Integrated Graphics driver: i915 v: kernel
</span><span> Display: x11 server: X.Org 1.20.7 driver: intel unloaded: modesetting resolution: 2560x1080~60Hz
</span><span> OpenGL: renderer: Mesa DRI Intel Haswell v: 4.5 Mesa 19.3.2
</span><span>Network: Device-1: Realtek RTL8111/8168/8411 PCI Express Gigabit Ethernet driver: r8168
</span><span>Drives: Local Storage: total: 577.55 GiB used: 343.00 GiB (59.4%)
</span><span>Info: Processes: 355 Uptime: 40m Memory: 6.72 GiB used: 4.79 GiB (71.3%) Shell: zsh inxi: 3.0.37
</span><span>
</span></code></pre>
<h2 id="a-master-node-installation">A. Master node installation</h2>
<p>Yang pertama harus disiapkan adalah node master untuk control plane.</p>
<h3 id="a1-dari-host-pc">A1. Dari host pc</h3>
<p>Dari host PC, aku launch lxc container untuk node master, kuberi nama kmaster. Berikut ini langkah demi langkahnya:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>➜ ~ lxc launch ubuntu:18.04 kmaster
</span><span>➜ ~ lxc stop kmaster
</span><span>➜ ~ lxc config device add kmaster "kmsg" unix-char source="/dev/kmsg" path="/dev/kmsg"
</span><span>➜ ~ lxc config show kmaster > kmaster.config
</span><span>➜ ~ vim kmaster.config
</span><span># tambahkan config berikut ini:
</span><span> limits.memory.swap: "false"
</span><span> linux.kernel_modules: ip_tables,ip6_tables,netlink_diag,nf_nat,overlay
</span><span> raw.lxc: "lxc.apparmor.profile=unconfined\nlxc.cap.drop= \nlxc.cgroup.devices.allow=a\nlxc.mount.auto=proc:rw
</span><span> sys:rw"
</span><span> security.nesting: "true"
</span><span> security.privileged: "true"
</span><span># end of tambahkan
</span><span>➜ ~ lxc config edit kmaster < kmaster.config
</span><span>➜ ~ lxc start kmaster
</span><span>➜ ~ lxc exec kmaster -- bash
</span></code></pre>
<h3 id="a2-dari-master-node">A2. Dari master node</h3>
<p>Dari dalam kmaster, aku install docker, kubelet, kubeadm, dan kubectl</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>root@kmaster:~# apt update
</span><span>root@kmaster:~# apt install docker.io
</span><span>root@kmaster:~# docker --version
</span><span>root@kmaster:~# apt install curl
</span><span>root@kmaster:~# curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add
</span><span>root@kmaster:~# apt-add-repository "deb http://apt.kubernetes.io/ kubernetes-xenial main"
</span><span>root@kmaster:~# apt-get install kubeadm kubelet kubectl
</span><span>root@kmaster:~# apt-mark hold kubeadm kubelet kubectl
</span><span>root@kmaster:~# kubeadm init --pod-network-cidr=10.244.0.0/16
</span><span>root@kmaster:~# mkdir -p $HOME/.kube
</span><span>root@kmaster:~# cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
</span><span>root@kmaster:~# chown $(id -u):$(id -g) $HOME/.kube/config
</span><span>root@kmaster:~# kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
</span></code></pre>
<h2 id="b-worker-node-installation">B. Worker node installation</h2>
<p>Yang kedua harus disiapkan adalah node worker</p>
<h3 id="b1-dari-host-pc">B1. Dari host pc</h3>
<p>Dari host PC, aku launch lxc container untuk node worker, kuberi nama kworker1. Berikut ini langkah demi langkahnya:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>➜ ~ lxc launch ubuntu:18.04 kworker1
</span><span>➜ ~ lxc stop kworker1
</span><span>➜ ~ lxc config device add kworker1 "kmsg" unix-char source="/dev/kmsg" path="/dev/kmsg"
</span><span>➜ ~ lxc config show kworker1 > kworker1.config
</span><span>➜ ~ vim kworker1.config
</span><span># tambahkan config berikut ini:
</span><span> limits.memory.swap: "false"
</span><span> linux.kernel_modules: ip_tables,ip6_tables,netlink_diag,nf_nat,overlay
</span><span> raw.lxc: "lxc.apparmor.profile=unconfined\nlxc.cap.drop= \nlxc.cgroup.devices.allow=a\nlxc.mount.auto=proc:rw
</span><span> sys:rw"
</span><span> security.nesting: "true"
</span><span> security.privileged: "true"
</span><span># end of tambahkan
</span><span>➜ ~ lxc config edit kworker1 < kworker1.config
</span><span>➜ ~ lxc start kworker1
</span><span>➜ ~ lxc exec kworker1 -- bash
</span></code></pre>
<h3 id="b2-worker-node1">B2. Worker Node1</h3>
<p>Dari dalam kworker1, aku install docker, kubelet, kubeadm, dan kubectl</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>root@kworker1:~# apt update
</span><span>root@kworker1:~# apt install docker.io
</span><span>root@kworker1:~# docker --version
</span><span>root@kworker1:~# apt install curl
</span><span>root@kworker1:~# curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add
</span><span>root@kworker1:~# apt-add-repository "deb http://apt.kubernetes.io/ kubernetes-xenial main"
</span><span>root@kworker1:~# apt-get install kubeadm kubelet kubectl
</span><span>root@kworker1:~# apt-mark hold kubeadm kubelet kubectl
</span><span>root@kworker1:~# kubeadm join 10.170.160.215:6443 --token 4z3630.jbsf9pl43ftoh8vj --discovery-token-ca-cert-hash sha256:d8f06587bd4dfc2d8ffee741927d50743103ed02e7704550187ba807df47f99a
</span></code></pre>
<h1 id="note">Note</h1>
<p>if we forgot join token, we can generate new one with this command in kmaster:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>root@kmaster:~# kubeadm token create --print-join-command 2>/dev/null
</span></code></pre>
Bash - Memasukan Filename ke Array
2020-01-15T14:11:21+07:00
2020-01-15T14:11:21+07:00
Unknown
https://www.sumarsono.com/bash-memasukan-filename-ke-array/
<p>Aku punya banyak file log, semuanya berekstensi .log. Aku ingin nama-nama file logku dimasukan ke array supaya aku bisa akses berdasarkan indexnya.
Ini akan memudahkan untuk diolah. Aku memang tidak jago bash, makanya aku tulis disini supaya kelak aku bisa baca lagi.</p>
<p>Cara yang ku lakukan untuk memasukan filename ke array di bash:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>cd /my/log/path/
</span><span>logs=(); for log in *.log; do logs+=($log); done`
</span></code></pre>
<p>Kira-kira begini alurnya:</p>
<ul>
<li>Pindah ke direktori dimana log-log ku disimpan</li>
<li><code>logs=()</code> itu membuat array kosong</li>
<li><code>for ... done</code> itu for loop.</li>
<li><code>logs+=($log)</code> itu append nama file ke array</li>
</ul>
<p>Jadi kurang lebih sih: satu demi satu nama file dengan ekstensi .log di append ke array yang bernama logs.
Sekarang array logs berisi semua filename log-log ku.</p>
<p>Untuk menampilkan array logs beserta nomor indexnya, aku pakai cara ini:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>for log in "${!logs[@]}"; do printf "%s\t%s\n" "$log" "${logs[$log]}"; done;
</span></code></pre>
<ul>
<li><code>${!logs[@]}</code> : Tampilkan semua index dari array logs</li>
</ul>
<p>Dengan modal pengetahuan bash array diatas, aku jadi terbantu untuk melakukan beberapa task.</p>
Cara usb reverse tethering Android dan Distro Linux
2020-01-15T12:21:53+07:00
2020-01-15T12:21:53+07:00
Unknown
https://www.sumarsono.com/cara-usb-reverse-tethering-android-dan-distro-linux/
<p>Biasanya, kita tethering usb android ke PC itu utk share koneksi internet hp ke PC. Nah, kali ini aku pengen kebalikannya.
Bagaimana caranya aku bisa share koneksi internet dari pc ke hp lewat USB? yang muncul pertama dalam otakku adalah reverse tether.</p>
<p>Kenapa repot-repor share internet pc ke hp lewat usb? karena access point lagi sekarat, koneksinya lemot minta ampun. Sedangkan koneksi kabel lan ke pc wus wus kenceng.
Jadi ya salah satu cara supaya hp ku bisa tetap online adalah dengan reverse tether usb.</p>
<p>Caranya sangat mudah, karena sudah ada orang-orang hebat diluar sana yang membuat toolnya. Berikut cara yang kutempuh:</p>
<ul>
<li>Nyalakan ADB di HP</li>
<li>Colok ke PC, start adb server di PC. Pastikan hp kita terdeksi via 'adb devices'</li>
<li>Download <a href="https://github.com/Genymobile/gnirehtet/releases">gnirehtet-rust-linux64</a></li>
<li>Extract hasil download</li>
<li>Masuk ke terminal dari hasil extract</li>
<li>jalankan perintah </li>
</ul>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>./gnirehtet run -d 8.8.8.8
</span></code></pre>
<ul>
<li>Akan muncul permintaan untuk aktifkan vpn di hp.</li>
<li>Selesai, HP kita bisa internetan lewat usb tether dari PC</li>
</ul>
Benerin .gitignore yang gak jalan
2020-01-03T07:29:41+07:00
2020-01-03T07:29:41+07:00
Unknown
https://www.sumarsono.com/benerin-gitignore-yang-gak-jalan/
<p>Aku punya repo di local dan remote. Kemudian aku edit .gitignore nambahin .env supaya gak ke push. Pas di test, ternyata .env masih ke push ke repo. <em>Shit</em>. Yah, aku emang masih bego soal git.</p>
<p>Solusi dari masalahku itu sangat sederhana:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">git rm -r --cached .
</span><span style="color:#282828;">git add .
</span><span style="color:#282828;">git commit -m </span><span style="color:#79740e;">"respect .gitignore"
</span><span style="color:#282828;">git push
</span></code></pre>
<p>Udah, gitu doang. Haha</p>
<p>Cool~</p>
Refleksi 2019
2019-12-31T12:02:39+07:00
2019-12-31T12:02:39+07:00
Unknown
https://www.sumarsono.com/refleksi-2019/
<p>Hari ini, hari terakhir tahun 2019. Banyak yang terjadi di tahun 2019. Aku menulis ini untuk refleksi diri dan menjadikan ini sebagai catatan agar tidak hilang. Suatu hari aku akan menua dan (mungkin) pikun. Walaupun sebenarnya aku bingung mau menulis apa. Merangkai kata sungguh tidak mudah. Banyak yang terjadi di tahun 2019, suka, duka, semua ada. Aku hanya akan menulis momen yang baik. Momen sedih biarlah tersimpan dalam <em>nala</em>.</p>
<h3 id="tunangan">Tunangan</h3>
<p>Aku mulai dari hal yang paling berkesan, di tahun 2019 aku tunangan. Tepat pada hari Senin, 1 April 2019. Ya, momen yang menegangkan, deg-degan, senang, dan haru menjadi satu. Aku dan keluargaku datang ke rumahnya, dan melamarnya. Aku dan dia tunangan dan memutuskan untuk menikah pada tahun 2020. </p>
<h3 id="pekerjaan-impian">Pekerjaan Impian</h3>
<p>Momen berkesan selanjutnya, aku mendapatkan pekerjaan yang aku impikan. Dulu, aku bercita-cita menjadi guru. Namun setelah terjun ke institusi pendidikan, aku mengurungkan cita-citaku karena beberapa sebab. Sejak saat itu aku memutuskan untuk bekerja sesuai dengan yang aku sukai dan aku tekuni. Aku ingin pekerjaan yang tidak jauh dari dunia linux. Ya, aku menekuni linux sejak lulus SMP, sebelum masuk SMK. </p>
<p>Aku memutuskan untuk menjadi System Administrator. Meskipun ilmuku belum seberapa, aku akan terus belajar. Selain itu, aku menginginkan tempat kerja terstruktur, tim yang solid dan terbuka, dan manajemen yang bagus, serta menginginkan keseimbangan jam kerja dan jam pribadi.</p>
<p>Aku mendapatkannya. Aku menjadi system administrator. Aku masuk ke tim yang solid, terbuka, terstruktur. Jam kerja yang ideal, Senin - Jumat (08.00 - 16.00). Jam pribadi tanpa gangguan, ijin yang mudah.</p>
<h3 id="teman-yang-baik">Teman yang baik</h3>
<p>Aku bertemu dengan orang-orang yang baik. Aku tidak bisa membalas semua kebaikan mereka. Semua kebaikan mereka akan aku teruskan menjadi estafet. Aku tidak akan melupakan mereka semua. </p>
<h3 id="harapan">Harapan</h3>
<p>Semoga tahun depan menjadi pribadi yang lebih baik. Semoga semua cita terwujud.</p>
Cara Swap Fungsi Tombol Caps Lock dengan ESC di KDE
2019-12-29T17:59:36+07:00
2019-12-29T17:59:36+07:00
Unknown
https://www.sumarsono.com/cara-swap-fungsi-tombol-caps-lock-dengan-esc-di-kde/
<p>Mengganti fungsi tombol Caps Lock di distro linux yang pakai KDE sangatlah mudah. Caranya, perhatikan gambar diatas, berikut ini langkah-langkahnya:</p>
<ul>
<li>Buka <strong>System Settings > Hardware > Input Devices > Advanced</strong>. </li>
<li>centang <strong>Configure keyboard options</strong></li>
<li>unfold bagian <strong>Caps Lock Behavior</strong></li>
<li>centang <strong>Swap ESC and Caps Lock</strong></li>
<li>Klik <strong>Apply</strong></li>
</ul>
<p>Selesai, sekarang fungsi caps lock berubah menjadi esc, sedangkan fungsi esc berubah menjadi casplock. Sangat mudah kan? seperti yang aku katakan, sangat mudah mengganti tombol Caps Lock menjadi Esc di KDE. </p>
<p>Btw, kenapa sih kita repot-repot mengganti fungsi tombol Casp Lock menjadi Esc? Alasan tiap orang mungkin berbeda, kurang lebih:</p>
<ul>
<li>Tidak butuh tombol Caps Lock krn sudah ada tombol Shift.</li>
<li>Tombol Esc terlalu jauh di jangkau jari. Bagi pengguna Vim, tombol esc ini crusial dan sering dipakai. Untuk memudahkan akses tombol esc maka salah satu caranya adalah menjadikan tombol Caps Lock sebagai Esc.</li>
</ul>
<p>Cool~</p>
Shortcut Keyboard Terminal Linux yang Sering Kupakai
2019-12-29T16:11:09+07:00
2019-12-29T16:11:09+07:00
Unknown
https://www.sumarsono.com/shortcut-keyboard-terminal-linux-yang-sering-kupakai/
<p>Pekerjaan sehari-hari tidak jauh dari terminal. Memanfaatkan <em>shortcut</em> untuk meringkas sesuatu, sangat membantu. Terminal emulator yang kupakai hanya dua: Konsole bawaan KDE dan Terminator. Tergantung <em>mood</em> pakai yang mana. Haha.</p>
<p>Nah, dari sekian banyak shortcut terminal linux, berikut ini yang sering aku pakai:</p>
<table><thead><tr><th>Shortcut</th><th>Fungsi</th></tr></thead><tbody>
<tr><td><strong>TAB</strong></td><td><em>auto complete</em></td></tr>
<tr><td><strong>CTRL+c</strong></td><td>cancel <em>task/command</em></td></tr>
<tr><td><strong>CTRL+a</strong></td><td>pergi ke awal baris</td></tr>
<tr><td><strong>CTRL+e</strong></td><td>pergi ke akhir baris</td></tr>
<tr><td><strong>CTRL+panah kanan atau panah kiri</strong></td><td>pindah kana/kiri per kata/sparator</td></tr>
<tr><td><strong>CTRL+d</strong></td><td>exit</td></tr>
<tr><td><strong>CTRL+l</strong></td><td>clear</td></tr>
<tr><td><strong>CTRL+z</strong></td><td>kirim task ke backround</td></tr>
<tr><td><strong>CTRL+r</strong></td><td>backsearch history</td></tr>
<tr><td><strong>ALT+BACKSPACE</strong></td><td>hapus per kata/sparator</td></tr>
</tbody></table>
<p>Itu beberapa yang hampir tiap hari kupakai. Tidak menutup kemungkinan akan bertambah di kemudian hari.</p>
Typora - Sebuah Markdown Editor yang Kece Badai
2019-12-27T19:47:16+07:00
2019-12-27T19:47:16+07:00
Unknown
https://www.sumarsono.com/typora-sebuah-markdown-editor-yang-kece-badai/
<p>Mengutip dari situs <a href="https://www.typora.io/">Typora</a>:</p>
<blockquote>
<p>Typora will give you a seamless experience as both a reader and a writer. It removes the preview window, mode switcher, syntax symbols of markdown source code, and all other unnecessary distractions. Replace them with a real live preview feature to help you concentrate on the content itself.</p>
</blockquote>
<p>Yang aku suka dari typora adalah:</p>
<ol>
<li>Ada tema gelap.</li>
<li>Ngebantu banget pas bikin table pakai markdown.</li>
<li>Feel-nya enak banget pas nulis markdown.</li>
<li>Cross platform, bahkan untuk linux ada versi binary yang tinggal run.</li>
</ol>
<p>Buat kalian yang demen nulis pakai markdown, demen nge-blog pakai SSG, ini typora layak kalian coba sebagai editor kalian.</p>
<p>Cool~</p>
Local Git Server Pakai Gitea
2019-12-27T19:31:19+07:00
2019-12-27T19:31:19+07:00
Unknown
https://www.sumarsono.com/local-git-server-pakai-gitea/
<p>Apa itu gitea?</p>
<blockquote>
<p>Gitea is an open-source forge software package for hosting software development version control using Git as well as other collaborative features like bug tracking, wikis and code review. It supports self-hosting but also provides a free public first-party instance. It is a fork of Gogs and is written in Go</p>
</blockquote>
<p>Bahan:</p>
<ul>
<li>Docker</li>
<li>Docker Compose</li>
<li>docker-compose.yaml</li>
</ul>
<pre data-lang="yaml" style="background-color:#fcf0ca;color:#282828aa;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span style="font-weight:bold;color:#407959;">version</span><span>: </span><span style="color:#79740e;">"2"
</span><span>
</span><span style="font-weight:bold;color:#407959;">networks</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">gitea</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">external</span><span>: </span><span style="color:#8f3f71;">false
</span><span>
</span><span style="font-weight:bold;color:#407959;">services</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">server</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">image</span><span>: </span><span style="color:#79740e;">gitea/gitea:1.10.0
</span><span> </span><span style="font-weight:bold;color:#407959;">environment</span><span>:
</span><span> - </span><span style="color:#79740e;">USER_UID=1000
</span><span> - </span><span style="color:#79740e;">USER_GID=1000
</span><span> - </span><span style="color:#79740e;">DB_TYPE=mysql
</span><span> - </span><span style="color:#79740e;">DB_HOST=db:3306
</span><span> - </span><span style="color:#79740e;">DB_NAME=gitea
</span><span> - </span><span style="color:#79740e;">DB_USER=gitea
</span><span> - </span><span style="color:#79740e;">DB_PASSWD=gitea
</span><span> </span><span style="font-weight:bold;color:#407959;">restart</span><span>: </span><span style="color:#79740e;">always
</span><span> </span><span style="font-weight:bold;color:#407959;">networks</span><span>:
</span><span> - </span><span style="color:#79740e;">gitea
</span><span> </span><span style="font-weight:bold;color:#407959;">volumes</span><span>:
</span><span> - </span><span style="color:#79740e;">./gitea:/data
</span><span> - </span><span style="color:#79740e;">/etc/timezone:/etc/timezone:ro
</span><span> - </span><span style="color:#79740e;">/etc/localtime:/etc/localtime:ro
</span><span> </span><span style="font-weight:bold;color:#407959;">ports</span><span>:
</span><span> - </span><span style="color:#79740e;">"3000:3000"
</span><span> - </span><span style="color:#79740e;">"22:22"
</span><span> </span><span style="font-weight:bold;color:#407959;">depends_on</span><span>:
</span><span> - </span><span style="color:#79740e;">db
</span><span>
</span><span> </span><span style="font-weight:bold;color:#407959;">db</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">image</span><span>: </span><span style="color:#79740e;">mysql:5.7
</span><span> </span><span style="font-weight:bold;color:#407959;">restart</span><span>: </span><span style="color:#79740e;">always
</span><span> </span><span style="font-weight:bold;color:#407959;">environment</span><span>:
</span><span> - </span><span style="color:#79740e;">MYSQL_ROOT_PASSWORD=gitea
</span><span> - </span><span style="color:#79740e;">MYSQL_USER=gitea
</span><span> - </span><span style="color:#79740e;">MYSQL_PASSWORD=gitea
</span><span> - </span><span style="color:#79740e;">MYSQL_DATABASE=gitea
</span><span> </span><span style="font-weight:bold;color:#407959;">networks</span><span>:
</span><span> - </span><span style="color:#79740e;">gitea
</span><span> </span><span style="font-weight:bold;color:#407959;">volumes</span><span>:
</span><span> - </span><span style="color:#79740e;">./mysql:/var/lib/mysql
</span></code></pre>
Desktopku
2019-12-27T09:25:03+07:00
2019-12-27T09:25:03+07:00
Unknown
https://www.sumarsono.com/desktopku/
<p>Sudah agak lama aku pakai KDE untuk laptop dan PC yg kupakai. Aku memang suka gnome, terutama konsep mereka yang <em>keep it stupid simple</em>. Tapi, semakin kesini gnome terasa aga <em>laggy</em>, dan boros resource, entah kenapa.</p>
<p>Itu sebabnya, aku pindah ke KDE. KDE yang sekarang sungguh beda dengan KDE yang dahulu. KDE sekarang sangat ringan dan smooth. Lebih mantep lagi KDE yg dipoles tim <a href="https://manjaro.org/">Manjaro</a>. Komposisi temanya sangat bagus, nyaman dipandang. <em>Saking</em> bagusnya sampai-sampai aku tidak berpikiran untuk ganti <em>theme</em>.</p>
<p>Kalian harus coba deh <a href="https://manjaro.org/">Manjaro</a> KDE.</p>
<p>Cool~</p>
Cara extract banyak file .tar.gz sekaligus dengan satu baris perintah
2019-12-10T08:47:04+07:00
2019-12-10T08:47:04+07:00
Unknown
https://www.sumarsono.com/cara-extract-banyak-file-tar-gz-sekaligus-dengan-satu-baris-perintah/
<p>Caranya cukup gampil. Eksekusi aja </p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>for file in *.tar.gz; do tar -zxf "$file"; done
</span></code></pre>
<p>Tambahan dari <a href="https://petruknisme.com/">@petruknisme</a>:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>find . -name '*.tar.gz' -execdir tar -xzvf '{}' \;
</span></code></pre>
<p>Note: ditambahin <code>--maxdepth <number></code> untuk seberapa jauh dia find data</p>
<p>Cool~</p>
Git checkout remote branch yang gak ada di lokal
2019-12-07T12:27:43+07:00
2019-12-07T12:27:43+07:00
Unknown
https://www.sumarsono.com/git-checkout-remote-branch-yang-gak-ada-di-lokal/
<p>Bukankah tinggal <code>git checkout nama-branch</code>? Nope. Biar ku jelaskan kasusnya krn ini masalah yang spesifik. Aku punya repo <a href="https://github.com/nalakawula/dummy">git@github.com:nalakawula/dummy.git</a>. Disana ada 3 branch: master, develop, dan staging. Suatu waktu, aku hanya clone satu branch saja, branch develop. Menggunakan perintah <code>git clone --single-branch --branch develop git@github.com:nalakawula/dummy.git</code>. Seiring berjalannya waktu, aku ada keperluan di branch staging. Ketika aku checkout branch staging di lokal:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>[semut@semut-pc dummy]$ git checkout staging
</span><span>error: pathspec 'staging' did not match any file(s) known to git
</span></code></pre>
<p>Hmm, check semua branch:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>[semut@semut-pc dummy]$ git branch -a
</span><span>* develop
</span><span> remotes/origin/develop
</span></code></pre>
<p>Ternyata, branch staging tidak terlist. Coba <code>git fetch</code> kemudian check lagi ternyata branch staging masih nihil. Padahal di repo jelas ada.</p>
<p>Solusinya adalah
Cek git config,</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>[semut@semut-pc dummy]$ git config --list | grep fetch
</span><span>remote.origin.fetch=+refs/heads/develop:refs/remotes/origin/develop
</span></code></pre>
<p>I see, ternyata repo lokalku hanya ngefetch satu branch doang efek pas clone pakai opsi <code>--single-branch</code>.</p>
<p>Aku harus ganti confignya biar fetch semuanya,</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>[semut@semut-pc dummy]$ git config remote.origin.fetch '+refs/heads/*:refs/remotes/origin/*'
</span></code></pre>
<p>Coba fetch lagi</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>[semut@semut-pc dummy]$ git fetch
</span><span>From github.com:nalakawula/dummy
</span><span> * [new branch] master -> origin/master
</span><span> * [new branch] staging -> origin/staging
</span></code></pre>
<p>Sekarang aku yakin bisa checkou branch staging</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>[semut@semut-pc dummy]$ git checkout staging
</span><span>Branch 'staging' set up to track remote branch 'staging' from 'origin'.
</span><span>Switched to a new branch 'staging'
</span></code></pre>
<p>Cek hasilnya</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>[semut@semut-pc dummy]$ git branch -a
</span><span> develop
</span><span>* staging
</span><span> remotes/origin/develop
</span><span> remotes/origin/master
</span><span> remotes/origin/staging
</span></code></pre>
<p>Sekarang aku sudah berada di branch staging.</p>
<p>Cool~</p>
SSH Jump Host
2019-11-28T13:19:48+07:00
2019-11-28T13:19:48+07:00
Unknown
https://www.sumarsono.com/ssh-jump-host/
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>++++++++++++++ ++++++++++ ++++++++++
</span><span>| mesin kita |-----| Host A |-----| Host B |
</span><span>++++++++++++++ ++++++++++ ++++++++++
</span></code></pre>
<p>Aku mau SSH ke Host B melalui Host A.</p>
<p>Sederhana, aku bisa saja <code>ssh user@hosta</code> kemudian dari dalam Host A aku eksekusi <code>ssh user@hostb</code>. Tapi eh tapi, aku kurang nyaman. Akan lebih baik kalau eksekusi sekali jalan.
Caranya cukup sederhana, setidaknya openssh punya fitur ini.</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>ssh -J user@hosta user@hostb
</span></code></pre>
<p>Gitu doang, beres.</p>
<p>Cool~</p>
Vuejs Docker
2019-11-22T19:18:26+07:00
2019-11-22T19:18:26+07:00
Unknown
https://www.sumarsono.com/vuejs-docker/
<p>Bikin frontend app pakai vuejs, enak kalau dibikin docker image buat publishnya. Berikut ini dua contoh docker untuk vuejs, contoh pertama pakai httpd untuk serve vuejs dan contoh kedua pakai nginx untuk serve vuejs.
Untuk contoh ini vue routernya pakai history mode.</p>
<h1 id="vuejs-docker-httpd">vuejs docker httpd</h1>
<p>Pertama, masuk ke direktori kerja app vue yang kita kerjakan.
Kemudian bikin file bernama <code>Dockerfile-httpd</code>, isi file tersebut adalah</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span># build stage
</span><span>FROM node:lts-alpine as build-stage
</span><span>WORKDIR /app
</span><span>COPY package*.json ./
</span><span>RUN npm install
</span><span>COPY . .
</span><span>RUN npm run build
</span><span>
</span><span># production stage
</span><span>FROM httpd:2.4-alpine as production-stage
</span><span>RUN sed -i '/LoadModule rewrite_module/s/^#//g' /usr/local/apache2/conf/httpd.conf && \
</span><span> sed -i 's#AllowOverride [Nn]one#AllowOverride All#' /usr/local/apache2/conf/httpd.conf
</span><span>COPY --from=build-stage /app/dist /usr/local/apache2/htdocs/
</span><span>COPY .htaccess /usr/local/apache2/htdocs/.htaccess
</span></code></pre>
<p>Selanjutnya, siapkan file <code>.htaccess</code> buat handle vue router history mode.</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span><IfModule mod_rewrite.c>
</span><span> RewriteEngine On
</span><span> RewriteBase /
</span><span> RewriteRule ^index\.html$ - [L]
</span><span> RewriteCond %{REQUEST_FILENAME} !-f
</span><span> RewriteCond %{REQUEST_FILENAME} !-d
</span><span> RewriteRule . /index.html [L]
</span><span></IfModule>
</span></code></pre>
<p>Selesai, tinggal build</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>docker build -t myusername/fehr:v1-httpd -f Dockerfile-httpd .
</span></code></pre>
<p>Hasil build bisa di cek pakai command <code>docker images</code>.</p>
<h1 id="vuejs-docker-nginx">vuejs docker nginx</h1>
<p>Pertama, masuk ke direktori kerja app vue yang kita kerjakan.
Kemudian bikin file bernama <code>Dockerfile-nginx</code>, isi file tersebut adalah</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span># build stage
</span><span>FROM node:lts-alpine as build-stage
</span><span>WORKDIR /app
</span><span>COPY package*.json ./
</span><span>RUN npm install
</span><span>COPY . .
</span><span>RUN npm run build
</span><span>
</span><span># production stage
</span><span>FROM nginx:stable-alpine as production-stage
</span><span>COPY nginx.conf /etc/nginx/conf.d/default.conf
</span><span>COPY --from=build-stage /app/dist /usr/share/nginx/html
</span><span>EXPOSE 80
</span><span>CMD ["nginx", "-g", "daemon off;"]
</span></code></pre>
<p>Selanjutnya siapkan file <code>nginx.conf</code> yang isinya</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>server {
</span><span> listen 80;
</span><span> server_name localhost;
</span><span>
</span><span> location / {
</span><span> root /usr/share/nginx/html;
</span><span> index index.html index.htm;
</span><span> try_files $uri $uri/ /index.html;
</span><span> }
</span><span>
</span><span> error_page 500 502 503 504 /50x.html;
</span><span> location = /50x.html {
</span><span> root /usr/share/nginx/html;
</span><span> }
</span><span>}
</span></code></pre>
<p>Lanjut build</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>docker build -t myusername/fehr:v1-nginx -f Dockerfile-nginx .
</span></code></pre>
<p>Selesai, tinggal run. Pilih versi httpd atau nginx bebas sesuai selera. Yang terlihat jelas bedanya adalah ukuran docker image hasil build. Untuk proyek vuejs yang sama, versi httpd menghasilkan image sebesar 138MB sedangkan versi nginx menghasilkan image sebesar 30.1MB. Itu di tempatku, kali aja di tempat kalian beda. hahaha
Cool~</p>
Cara Mudah Bikin DNS Server Lokal Pakai CoreDNS
2019-11-05T19:11:02+07:00
2019-11-05T19:11:02+07:00
Unknown
https://www.sumarsono.com/cara-mudah-bikin-dns-server-lokal-pakai-coredns/
<p>Wtf is coreDNS?</p>
<blockquote>
<p>CoreDNS is a DNS server. It is written in Go. It can be used in a multitude of environments because of its flexibility. CoreDNS is licensed under the Apache License Version 2, and completely open source. -- <a href="https://coredns.io/">coredns.io</a></p>
</blockquote>
<p>Singkat cerita, aku pengen ketika temenku buka browser, ngetik alamat fe.anuanku.dev dia akan disajikan halaman web dari komputer dengan alamat 192.168.100.137. Terus, kalau temenku akses api.anuanku.dev akan disajikan API dari komputer dengan alamat 192.168.100.137. Paham kan ya? seolah-olah kaya akses vhost di vps.</p>
<p>Kenapa gk pakai cara edit file <code>hosts</code> saja? ribet cuy. Ya masa aku nyuruh temenku edit host file. Gak enak juga nyuruh-nyuruh haha. Lanjut ke step by step yang ku tempuh:</p>
<p>Persiapan directory</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>mkdir ~/coredns/coredns-config
</span></code></pre>
<p>Bikin <code>~/coredns/docker-compose.yaml</code> yang berisi</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>version: '3.7'
</span><span>services:
</span><span> coredns:
</span><span> image: coredns/coredns
</span><span> restart: always
</span><span> command: -conf /coredns-config/Corefile
</span><span> ports:
</span><span> - 53:53/udp
</span><span> volumes:
</span><span> - ./coredns-config:/coredns-config/
</span></code></pre>
<p>Bikin <code>~/coredns/coredns-config/Corefie</code> yang berisi</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>.:53 {
</span><span> forward . 9.9.9.9
</span><span> log
</span><span> errors
</span><span>}
</span><span>
</span><span>anuanku.dev:53 {
</span><span> file /coredns-config/anuanku.dev.db
</span><span> log
</span><span> errors
</span><span>}
</span><span>
</span></code></pre>
<p>Bikin <code>~/coredns/coredns-config/anuanku.dev.db</code> yang berisi</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>anuanku.dev. IN SOA dns.anuanku.dev. sumar.anuanku.dev. 2019110517 7200 3600 1209600 3600
</span><span>fe.anuanku.dev. IN A 192.168.100.137
</span><span>api.anuanku.dev. IN A 192.168.100.137
</span></code></pre>
<p>Selesai persiapan, langsung eksekusi</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>docker-compose -f ~/coredns/docker-compose.yaml up -d
</span></code></pre>
<p>Hasilnya jika di test:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>drill @127.0.0.1 fe.anuanku.dev
</span><span>;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 35602
</span><span>;; flags: qr aa rd ; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
</span><span>;; QUESTION SECTION:
</span><span>;; fe.anuanku.dev. IN A
</span><span>
</span><span>;; ANSWER SECTION:
</span><span>fe.anuanku.dev. 0 IN A 192.168.100.137
</span><span>
</span><span>;; AUTHORITY SECTION:
</span><span>
</span><span>;; ADDITIONAL SECTION:
</span><span>
</span><span>;; Query time: 2 msec
</span><span>;; SERVER: 127.0.0.1
</span><span>;; WHEN: Tue Nov 5 19:30:57 2019
</span><span>;; MSG SIZE rcvd: 56
</span></code></pre>
<p>Udah selesai, tinggal ganti dns router ke ip address komputer yang ngejalanin coreDNS. Ataus suruh temenku ganti dns-nya di network manager (tapi gak enak nyuruh2, haha).
Sisanya ya kombinasikan aja sama vhost, entah nginx, httpd, atau traefik.</p>
<p>Cool~</p>
Logrotate Traefik
2019-10-30T13:08:20+07:00
2019-10-30T13:08:20+07:00
Unknown
https://www.sumarsono.com/logrotate-traefik/
<p>Aku pakai traefik untuk ingress controller k8s cluster. Dulu pas setup, aku aktifin access log karena mau aku analisa (Ceileh sok sokan haha).
Setelah sekian bulan, log nya traefik bengkak. Haha. Asem, aku lupa rotasi log-nya. Catet dalam benak, logrotate itu wajib untuk sesuatu yang jalan selamanya.</p>
<p>Tanpa cas cis cus, langsung bikin logrotate</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo vim /etc/logrotate.d/traefik
</span></code></pre>
<p>Isinya adalah</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>/var/log/traefik/access.log
</span><span>{
</span><span> compress
</span><span> create 0640 root root
</span><span> daily
</span><span> delaycompress
</span><span> missingok
</span><span> notifempty
</span><span> rotate 30
</span><span>
</span><span> postrotate
</span><span> kill -USR1 `pgrep traefik`
</span><span> endscript
</span><span>}
</span></code></pre>
<p>Selesai, sisanya serahkan kepada sistem. Kita leyeh-leyeh.
Cool~</p>
Mencoba Traefik v2
2019-10-20T16:17:30+07:00
2019-10-20T16:17:30+07:00
Unknown
https://www.sumarsono.com/mencoba-traefik-v2/
<p><a href="https://docs.traefik.io/">Traefik</a>, belum lama ini rilis versi 2.0. Good news dan bad news. Good news karena pastinya membawa fitur yang makin caem. Bad news karena perubahannya nge-break traefik v1.7. Artinya konfigurasi yang kupakai di traefik v1.7 tidak bisa kupakai begitu saja di traefik v2. Jadinya senang dan sedih campur jadi satu. Namun demikian, life must go on. Aku gak bisa stuck di traefik v1.7 untuk selamanya. Rencanaku, aku mau nunggu sampai traefik v2.1 rilis baru aku migrasi. Soalnya, traefik v1.7 yang kupakai sejauh ini ya fine aja ditambah lagi traefik v2 masih ada kekurangan di dokumentasinya. Oh iya, aku pakai traefik untuk ingress cluster kubernetes. Namun untuk coba-coba ini aku tidak akan pakai klaster k8s.</p>
<p>Meskipun berencana migrasi setelah traefik v2.1 rilis, aku tetap harus mencoba traefik v2 sedini mungkin. Demi memahami segala perubahannya dan mempersiapkan diri untuk migrasi. Migrasi tidaklah semudah membalik telapak tangan kalau breaking changes-nya masif.</p>
<p>Untuk studi kasus yang akan ku lakukan adalah dengan mencoba expose service dengan backend file dan docker. Backend untuk traefik ini banyak soalnya, ada file, docker, kubernetes, rancher, dll.</p>
<p>Untuk backend file, aku mau expose nginx legacy (maksudnya non docker). Nginx ini akan aku bind ke port 81. Goalnya adalah ketika aku GET url localhost/nginx maka akan muncul halaman default nginx. Dalam hal ini, traefik akan di set untuk watch sebuah directory, begitu ada perubahan pada directory tersebut traefik akan otomatis baca dan menyesuaikan.</p>
<p>Sedangkan untuk backend docker, aku mau expose service docker containous/whoami. Goalnya adalah ketika aku GET url localhost/whoami akan muncul halaman dari docker containous/whoami. Enaknya traefik untuk ekspose kontainer docker ini, kita gak perlu repot bikin konfigurasi dan mapping port satu satu. Cukup main label di kontainer yang mau di expose. Traefik akan otomatis bikin konfigurasinya. Asyik kan. Haha.</p>
<p>Langkah pertama, tentu saja siapkan traefik v2:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>mkdir -p /penyimpananBersama/docker/traefikv2
</span><span>cd /penyimpananBersama/docker/traefikv2
</span><span>vim docker-compose.yaml
</span></code></pre>
<p>file docker-compose.yaml tersebut isinya:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>version: "3.3"
</span><span>
</span><span>services:
</span><span> traefik:
</span><span> image: "traefik:v2.0"
</span><span> container_name: "traefik"
</span><span> command:
</span><span> - "--log.level=DEBUG"
</span><span> - "--accesslog=true"
</span><span> - "--api.insecure=true"
</span><span> - "--providers.docker=true" # aktifkan backend docker
</span><span> - "--providers.file.directory=/myconf" # aktifkan backend file
</span><span> - "--providers.file.watch=true" # watch perubahan backend file
</span><span> - "--providers.docker.exposedbydefault=false"
</span><span> - "--entrypoints.web.address=:80"
</span><span> - "--entryPoints.websecure.address=:443"
</span><span> - "--certificatesresolvers.mytlschallenge.acme.tlschallenge=true"
</span><span> - "--certificatesresolvers.mytlschallenge.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
</span><span> - "--certificatesresolvers.mytlschallenge.acme.email=postmaster@sumarsono.com"
</span><span> - "--certificatesresolvers.mytlschallenge.acme.storage=/letsencrypt/acme.json"
</span><span> ports:
</span><span> - "80:80"
</span><span> - "443:443"
</span><span> - "8080:8080"
</span><span> volumes:
</span><span> - "/var/run/docker.sock:/var/run/docker.sock:ro"
</span><span> - "./letsencrypt:/letsencrypt"
</span><span> - "./myconf:/myconf"
</span><span> networks:
</span><span> - web
</span><span>
</span><span>networks:
</span><span> web:
</span><span> external: true
</span></code></pre>
<p>Langkah kedua adalah run traefik v2:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>cd /penyimpananBersama/docker/traefikv2
</span><span>docker network create web
</span><span>docker-compose up -d
</span></code></pre>
<p>Langkah ketiga, uji coba backend file dengan cara install nginx, bind nginx ke port 81 kemudian start service nginx. Baru kemudian kita coba expose pakai traefik v2:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span># pakai sudo krn directory ini milik root
</span><span>sudo vim /penyimpananBersama/docker/traefikv2/myconf/test.yaml
</span></code></pre>
<p>isi dari file test.yaml adalah sebagai berikut:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>http:
</span><span> # Add the router
</span><span> routers:
</span><span> router-legacy:
</span><span> entryPoints:
</span><span> - web
</span><span> middlewares:
</span><span> - "test-stripprefix"
</span><span> service: service-nginx
</span><span> rule: "Host(`localhost`) && PathPrefix(`/nginx`)"
</span><span>
</span><span> # Add the middleware
</span><span> middlewares:
</span><span> test-stripprefix:
</span><span> stripPrefix:
</span><span> prefixes:
</span><span> - "/nginx"
</span><span>
</span><span> # Add the service
</span><span> services:
</span><span> service-nginx:
</span><span> loadBalancer:
</span><span> servers:
</span><span>
</span><span>
</span><span> passHostHeader: false
</span></code></pre>
<p>Maksud dari konfigurasi diatas adalah request ke localhost/nginx akan diteruskan ke http://172.17.0.1:81/ dengan path /nginx nya dibuang. Karena nginx tersebut servenya path /.</p>
<p>Bukalah localhost:8080, mestinya traefik v2 udah ngebaca rule yang kita bikin secara otomatis. Terus bukalah localhost/nginx, hasilnya akan sama dengan akses localhost:81. Cool~</p>
<p>Berikutnya aku mau coba expose service docker container. dalam hal ini aku mau pakai containous/whoami.
Pertama, kita siapkan compose utk service tersebut:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>mkdir /penyimpananBersama/docker/whoami/
</span><span>vim /penyimpananBersama/docker/whoami/docker-compose.yaml
</span></code></pre>
<p>Isi dari docker-compose.yaml ini adalah:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>version: "3.3"
</span><span>
</span><span>services:
</span><span> whoami:
</span><span> image: "containous/whoami"
</span><span> container_name: "whoami"
</span><span> labels:
</span><span> - "traefik.enable=true"
</span><span> - "traefik.http.routers.whoami.rule=Host(`localhost`) && Path(`/whoami`)"
</span><span> - "traefik.http.routers.whoami.entrypoints=web"
</span><span> networks:
</span><span> - web
</span><span>networks:
</span><span> # network ini tadi udah dibikin pas mau run traefik v2
</span><span> web:
</span><span> external: true
</span><span>
</span></code></pre>
<p>Kuncinya ada pada labels. Label itulah yang akan dibaca traefik dan otomatis dibuatkan tetek bengeknya sama traefik v2.</p>
<p>Selanjutnya tinggal jalankan:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>cd /penyimpananBersama/docker/whoami
</span><span>docker-compose up -d
</span></code></pre>
<p>Tinggal tes, coba buka localhost/whoami. Coba juga buka dashboard traefik v2 localhost:8080.</p>
<p>Selesai, so far so good. Masih banyak PR nya, test issue cert LE, eksplor middleware (di traefik v1 belum ada), explore dynamic conf, dll.</p>
<script async src="https://telegram.org/js/telegram-widget.js?7" data-telegram-post="unomindgithubio/54" data-width="100%"></script>
<p>Cool~</p>
Memanfaatkan Tor Hidden Service untuk Mengakses Komputer Lokal dari Internet
2019-10-20T10:49:00+07:00
2019-10-20T10:49:00+07:00
Unknown
https://www.sumarsono.com/memanfaatkan-tor-hidden-service-untuk-mengakses-komputer-lokal-dari-internet/
<p>Apa itu Tor? <a href="https://www.torproject.org/">Klik disini</a>.
Apa itu Tor hidden service? <a href="https://2019.www.torproject.org/docs/tor-onion-service">Klik disni</a>.
Sepemahaman <em>my dumb ass brain</em>, Tor hidden service ini bikin alamat .onion yang bisa di akses dari jaringan Tor. Nah hal sepeti ini akan sangat membantu kita untuk akses komputer lokal dari Internet. Contohnya, di rumah aku punya PC yang terhubung ke Internet dan aku tidak bisa set port forward karena tidak pegang routernya. Di PC tersebut, terinstall web server yang ingin aku akses dari luar kota. Di PC tersebut juga terinstall ssh server untuk kubutuhan administrasi secara remote, aku ingin PC itu bisa di remote dari luar kota.</p>
<p>Solusinya ada banyak, bisa pakai port forward di router kalau kita ada akses ke router. Bisa pakai jasa <a href="https://ngrok.io">ngrok.io</a>, <a href="http://tunn.ml">tunn.ml</a>, atau serveo. Bisa juga pakai VPN gateway, misalnya bikin wireguard mesh. Nah, alternatif lain adalah pakai Tor Hidden Service.</p>
<p>Caranya sangat mudah, dalam kasus ini aku pakai OS <a href="https://manjaro.org/">Manjaro</a>. Pertama aku install paket tor:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo pacman -S tor torsocks
</span></code></pre>
<p>Kedua, bikin tor hidden service dengan cara edit berkas <code>/etc/tor/torrc</code>:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo nano /etc/tor/torrc
</span></code></pre>
<p>Carilah baris <code>This section is just for location-hidden services</code>, disitu ada contohnya. Aku cuma bikin begini:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>HiddenServiceDir /var/lib/tor/hidden_web/
</span><span>HiddenServicePort 80 127.0.0.1:80
</span><span>HiddenServicePort 443 127.0.0.1:443
</span><span>
</span><span>HiddenServiceDir /var/lib/tor/hidden_ssh/
</span><span>HiddenServicePort 2222 127.0.0.1:2222
</span></code></pre>
<p>Web serverku jalan di port 80 dan 443, sedangkan ssh ku jalan di port 2222.</p>
<p>Langkah ketiga, enable dan start service Tor</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo systemctl enable --now tor
</span></code></pre>
<p>Langkah terakhir adalah mendapatkan alamat .onion untuk hidden service kita. Alamat tersebut tersimpan di file hostname di dalam HiddenServiceDir:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo su
</span><span>cat /var/lib/tor/hidden_web/hostname
</span><span>longrandomstringhidden_web.onion
</span><span>
</span><span>cat /var/lib/tor/hidden_ssh/hostname
</span><span>longrandomstringhidden_ssh.onion
</span></code></pre>
<p>Selesai, tinggal catat alamat .onion-nya. Alamat tersebut sudah bisa di akses dari internet lewat jaringan Tor.</p>
<p>Jadi untuk akses alamat tersebut, kita harus install tor juga di komputer yang mau akses. Untuk akses hidden service yang web, aku pakai tor browser dari repo Aur. Tinggal buka tor browser dan pergi ke alamat longrandomstringhidden_web.onion.
Contohnya berikut ini:
<img src="/assets/images/contoh-akses-hidden-service-web.webp" alt="contoh-akses-hidden-service-web.webp" title="akses tor hidden service web" /></p>
<p>Sedangkan untuk hidden service ssh aku pakai cara ini:</p>
<p>Pertama aku bikin ssh config:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>host pcrumah
</span><span> hostname longrandomstringhidden_ssh.onion
</span><span> user sumar
</span><span> port 2222
</span><span> identityfile "/path/to/my/key.pem"
</span><span> #proxyCommand ncat --proxy 127.0.0.1:9050 --proxy-type socks5 %h %p # pakai ini kalau punya paket ncat, jadi gak perlu torify
</span></code></pre>
<p>Kedua, tinggal eksekusi:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>torify ssh pcrumah
</span></code></pre>
<p>Selesai. Cool~</p>
<blockquote>
<p>Tips: Untuk alasan keamanan, aku disable ssh root login dan disable password auth untuk ssh.</p>
</blockquote>
Bikin File PPK di Linux
2019-10-11T06:13:08+07:00
2019-10-11T06:13:08+07:00
Unknown
https://www.sumarsono.com/bikin-file-ppk-di-linux/
<p>File .ppk dibutuhkan oleh putty, filezilla, dan beberapa ssh klien di windows untuk login ke ssh tanpa password.
Kalau kita kerja sendirian mah gak perlu hal ginian. Cuma kalau kerja bareng tim, ada kalanya temen dalam tim butuh akses ke server.
Untuk bikin ppk file di linux kita butuh puttygen. Install aja karena ada di repo resmi beberapa distro.</p>
<p>Di Arch Linux:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>pacman -S putty
</span></code></pre>
<p>Di RHEL/Centos:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>yum install putty
</span></code></pre>
<p>Di Fedora:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>dnf install putty
</span></code></pre>
<p>Debian/Ubuntu:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>apt-get install putty-tools
</span></code></pre>
<p>Cara pakainya juga mudah:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>cd /home/user/.ssh/
</span><span>puttygen id_rsa -o ssh-key.ppk
</span></code></pre>
<p>Selesai, tinggal kasih aja ke tim tuh ppk.</p>
<p>Kenapa pakai key? gak password aja? Anu, botnet sekarang mengerikan, jadinya ssh pakai password itu gak gimana gitu rasanya.</p>
<p>Cool~</p>
LXD auto completion plugin untuk oh-my-zsh
2019-09-27T03:00:48+07:00
2019-09-27T03:00:48+07:00
Unknown
https://www.sumarsono.com/lxd-auto-completion-plugin-untuk-oh-my-zsh/
<p>Pertama masuk ke direktori custom plugin oh-my-zsh</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>cd /usr/share/oh-my-zsh/custom/plugins
</span></code></pre>
<p>Lalu, clone repo milik endaaman</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo git clone https://github.com/endaaman/lxd-completion-zsh.git
</span></code></pre>
<p>Selanjutnya, masuk ke folder hasil clone kemudian lakukan symlink</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>cd lxd-completion-zsh
</span><span>sudo ln -sf _lxc lxd-completion-zsh.plugin.zsh
</span></code></pre>
<p>Terakhir, edit zshrc untuk load plugin</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>vim ~/.zshrc
</span></code></pre>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>plugins=(
</span><span> ...
</span><span> lxd-completion-zsh
</span><span>)
</span></code></pre>
<p>Tes dah,</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>$ lxc st+TAB
</span><span>start -- Start containers
</span><span>stop -- Stop containers
</span><span>storage -- Manage storage pools and volumes
</span><span>
</span><span>$ lxc start +TAB
</span><span>kmaster tpl-kube
</span></code></pre>
<p>Cool!</p>
Bikin lxc container dapet IP address dari router
2019-09-26T17:41:19+07:00
2019-09-26T17:41:19+07:00
Unknown
https://www.sumarsono.com/bikin-lxc-container-dapet-ip-address-dari-router/
<p>Secara default, lxc (dalam hal ini aku pakai lxd) container akan pakai profile bernama default.
Di profile default tersebut, didefinisikan bahwa container akan pakai network mode bridge dengan parent lxdbr0.
Oleh sebab itu, container tidak akan mendapatkan ip dari router.</p>
<p>Supaya container mendapat ip dari router, maka kita harus ganti nictype bridge menjadi macvlan.
Kemudian ganti parent menjadi eth fisik yang dalam hal ini adalah enp2s0 (kita bisa dapetin dengan <code>ip link</code>)</p>
<p>Ringkasan langkah-langkah yang ku tempuh:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>lxc profile list # lihat daftar profile lxc
</span><span>lxc profile copy default macvlanprofile # copy profile default
</span><span>ip link # cek nama perangkat fisik
</span><span>lxc profile device set macvlanprofile eth0 nictype macvlan # ubah nictype menjadi macvlan
</span><span>lxc profile device set macvlanprofile eth0 parent enp2s0 # ubah parent menjadi perangkat fisik
</span><span>lxc profile show macvlanprofile # lihat hasil edit
</span><span>lxc launch -p macvlanprofile ubuntu:16.04 net1 # tes bikin container pakai profile macvlanprofile
</span><span>lxc list # cek list container, disini tertera bahwa ip container dapet dari router
</span><span>lxc exec net1 ip route # untuk memastikan ip container
</span></code></pre>
<p>Biar lebih jelas,</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>$ ip a show enp2s0
</span><span>2: enp2s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
</span><span> link/ether f4:4d:30:a7:57:7c brd ff:ff:ff:ff:ff:ff
</span><span> inet 192.168.1.28/24 brd 192.168.1.255 scope global noprefixroute enp2s0
</span><span> valid_lft forever preferred_lft forever
</span><span> inet6 fe80::10bc:5396:d876:5572/64 scope link noprefixroute
</span><span> valid_lft forever preferred_lft forever
</span><span>
</span><span>$ lxc list
</span><span>+---------+---------+---------------------+------------------------------------------------+------------+-----------+
</span><span>| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
</span><span>+---------+---------+---------------------+------------------------------------------------+------------+-----------+
</span><span>| centos7 | STOPPED | | | PERSISTENT | 0 |
</span><span>+---------+---------+---------------------+------------------------------------------------+------------+-----------+
</span><span>| gitea | RUNNING | 10.70.3.189 (eth0) | fd42:a719:f701:92e0:c513:3a0a:d11f:c264 (eth0) | PERSISTENT | 0 |
</span><span>+---------+---------+---------------------+------------------------------------------------+------------+-----------+
</span><span>| net1 | RUNNING | 192.168.1.86 (eth0) | | PERSISTENT | 0 |
</span><span>+---------+---------+---------------------+------------------------------------------------+------------+-----------+
</span></code></pre>
<p>container gitea pakai mode bridge vs container net1 pakai mode macvlan.</p>
<p>Sekarang, perangkat dalam jaringan bisa komunikasi langsung dengan container yang kita buat.
Cool!</p>
<p>Tapi coba ping dari host ke container. Host tidak bisa komunikasi dengan container yang pakai macvlan.
Solusinya, bikin macvlan di host.</p>
<p>Agar macvlan yang dibuat di host tidak menggangu route enp2s0, maka aku bikin macvlan0 mode static tanpa gateway:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo vim /etc/netctl/macvlan0
</span></code></pre>
<p>Contoh konfigurasi macvlan0 static</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>Description='Virtual LAN with a static MAC on interface eth0 using DHCP'
</span><span>Interface=macvlan0
</span><span>Connection=macvlan
</span><span>BindsToInterfaces=enp2s0
</span><span>Mode="bridge"
</span><span>MACAddress="12:34:56:78:9a:bc"
</span><span>#IP=dhcp
</span><span>IP=static
</span><span>Address=('192.168.1.88/24')
</span></code></pre>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo netctl restart macvlan0
</span></code></pre>
<p>Dari sini, host sudah bisa komunikasi sama si container. Route utama juga tidak terganggu.</p>
<p>Cool!</p>
<p>Referensi:</p>
<ul>
<li><a href="https://blog.simos.info/how-to-make-your-lxd-container-get-ip-addresses-from-your-lan/">https://blog.simos.info/how-to-make-your-lxd-container-get-ip-addresses-from-your-lan/</a></li>
<li><a href="https://sreeninet.wordpress.com/2016/05/29/macvlan-and-ipvlan/">https://sreeninet.wordpress.com/2016/05/29/macvlan-and-ipvlan/</a></li>
<li><a href="https://developers.redhat.com/blog/2018/10/22/introduction-to-linux-interfaces-for-virtual-networking/#macvlan">https://developers.redhat.com/blog/2018/10/22/introduction-to-linux-interfaces-for-virtual-networking/#macvlan</a></li>
<li><a href="https://www.ostechnix.com/configure-static-dynamic-ip-address-arch-linux/">https://www.ostechnix.com/configure-static-dynamic-ip-address-arch-linux/</a></li>
</ul>
Bikin macvlan di Arch Linux dan turunannya serta semua distro yang menggunakan netplan
2019-09-25T17:51:15+07:00
2019-09-25T17:51:15+07:00
Unknown
https://www.sumarsono.com/bikin-macvlan-di-arch-linux-dan-turunannya-serta-semua-distro-yang-menggunakan-netplan/
<blockquote>
<p>Macvlan allows a single physical interface to have multiple mac and ip addresses using macvlan sub-interfaces.
This is different from creating sub-interface on a physical interface using vlan.
With vlan sub-interfaces, each sub-interface belongs to a different L2 domain using vlan and all sub-interfaces have same mac address.
With macvlan, each sub-interface will get unique mac and ip address and will be exposed directly in underlay network. </p>
</blockquote>
<blockquote>
<p>Macvlan interface is typically used for virtualization applications and each macvlan interface is connected to a Container or VM.
Each container or VM can directly get dhcp address from a common server as the host would do.
This would help customers who want Containers to be part of their traditional network with the IP addressing scheme that they already have. </p>
</blockquote>
<blockquote>
<p>Macvlan has 4 types(Private, VEPA, Bridge, Passthru). Commonly used type is Macvlan bridge which allows for endpoints in a single host to be able to talk to each other without packets leaving the host. For external connectivity, underlay network is used.</p>
</blockquote>
<blockquote>
<p>-- <a href="https://sreeninet.wordpress.com/2016/05/29/macvlan-and-ipvlan/">Source</a></p>
</blockquote>
<p>Daripada aku jelasin malah salah tangkap, jadi saya kutip saja. Jadi ceritanya aku ada PC terhubung ke router, PC itu punya satu ethernet card.
Aku pengen PC itu punya satu lagi ethernet card yang sama-sama terhubung ke router. Dan dapat ip yang satu kelas dari router. Salah satu caranya adalah dengan bikin eth virtual dari eth fisik yang ada.</p>
<p>Cara ini berlaku untuk semua distro yang membawa netplan untuk manajemen network. Contoh distro yang bawa netplan Arch linux, Manjaro, dan Ubuntu teranyar.</p>
<p>Pertama, copy contoh konfigurasi bawaan paket. Di Manjaro sih ada, entah di distro lain</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo cp /etc/netctl/examples/macvlan-dhcp /etc/netctl/macvlan0
</span></code></pre>
<p>Selanjutnya edit hasil copas tadi</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo vim /etc/netctl/macvlan0
</span></code></pre>
<p>Contoh punyaku seperti ini, silakan sesuaikan</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>Description='Virtual LAN with a static MAC on interface eth0 using DHCP'
</span><span>Interface=macvlan0 # nama interface yang mau kita buat
</span><span>Connection=macvlan
</span><span>BindsToInterfaces=enp2s0 # eth fisik yang sudah ada (dapat dari command `ip link`)
</span><span>Mode="bridge"
</span><span>MACAddress="12:34:56:78:9a:bc"
</span><span>IP=dhcp
</span></code></pre>
<p>Terakhir, tinggal start dan enable macvlan0 yang barusan dibuat</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo netctl enable macvlan0
</span><span>sudo netctl start macvlan0
</span></code></pre>
<p>Untuk memastikan, bisa cek pakai command <code>ip</code></p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>ip a
</span></code></pre>
<p>Hasilnya</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
</span><span> link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
</span><span> inet 127.0.0.1/8 scope host lo
</span><span> valid_lft forever preferred_lft forever
</span><span> inet6 ::1/128 scope host
</span><span> valid_lft forever preferred_lft forever
</span><span>2: enp2s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
</span><span> link/ether f4:4d:30:a7:57:7c brd ff:ff:ff:ff:ff:ff
</span><span> inet 192.168.1.28/24 brd 192.168.1.255 scope global noprefixroute enp2s0
</span><span> valid_lft forever preferred_lft forever
</span><span> inet6 fe80::10bc:5396:d876:5572/64 scope link noprefixroute
</span><span> valid_lft forever preferred_lft forever
</span><span>24: macvlan0@enp2s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
</span><span> link/ether 12:34:56:78:9a:bc brd ff:ff:ff:ff:ff:ff
</span><span> inet 192.168.1.88/24 brd 192.168.1.255 scope global noprefixroute macvlan0
</span><span> valid_lft forever preferred_lft forever
</span><span> inet6 fe80::1034:56ff:fe78:9abc/64 scope link
</span><span> valid_lft forever preferred_lft forever
</span></code></pre>
<p>Nah sip, selesai.
<code>enp2s0</code> itu perangkat eth fisik di PC dan dapet 192.168.1.28 dari router. <code>macvlan0@enp2s0</code> itu perangkat eth virtual yang tadi dibuat, dapet ip 192.168.1.88 dari router.</p>
<p>Cool!</p>
Aku menghapus akun fb dan ig dan tidak ada hal ajaib terjadi
2019-09-20T19:56:33+07:00
2019-09-20T19:56:33+07:00
Unknown
https://www.sumarsono.com/aku-mengapus-akun-fb-dan-ig-dan-tidak-ada-hal-ajaib-terjadi/
<p>Jauh hari sebelum menghapus akun facebook dan instagram, ada hal-hal yang mengganggu pikiranku. Kenapa aku melakukan ini?. Pertanyaan itu muncul ketika aku membuka sosial media. Update status, upload foto, untuk semua orang yang bahkan aku gak tahu, aku gak kenal, yang bahkan gak kontribusi apapun ke hidup aku. </p>
<p>Demi apa? demi siapa? apa yang aku harapkan? berharap komentar? berharap like? berharap perhatian? perhatian siapa?</p>
<p>Jika ada yang komentar, jika ada yang like, lalu apa? apa yang aku dapatkan? Apakah aku bahagia? kalau bahagia, sebahagia apa?
Kurang bahagiakah hidup aku?</p>
<p>Jika ada yang komentar, jika ada yang like, lalu apa? apa yang aku dapatkan? Apakah aku mendapatkan perhatian?
Secaper itukah aku?</p>
<p>Ketika aku membuka sosial media, apa yang terjadi? scroll scroll scroll, close. Buka lagi, scroll scroll scroll, close. Dan seterusnya. Apa manfaatnya? gak ada. Kurang kerjaan banget ya, 1/2 jam, 1 jam, habis untuk scroll scroll.</p>
<p>APA HAL NYATA YANG AKU DAPATKAN SETELAH SEMUA ITU? <strong>nothing</strong></p>
<p>Kalau aku tidak melakukan semua hal itu, apakah akan ada hal buruk yang menimpaku? apakah aku akan mati? apakah aku akan tidak bahagia?</p>
<p>Sampai tiba kasus Cambridge Analityca. Saat itu tekadku bulat untuk menghapus akun facebook dan instagram. </p>
<p>Setelah sekian lama, tidak ada hal ajaib terjadi. TENTU SAJA! aku menghapus akun bukan untuk mendapatkan keajaiban. Dan tentu, ada banyak yang terjadi. Hal paling sederhana adalah ketika aku pergi ke suatu tempat, aku benar-benar menikmati tempat itu! Merasakan semua keadaan sekitar! Tidak ada lagi gerakan bawah sadar untuk jepret-jepret demi sosial media.
Aku benar-benar menikmatinya! Dalam hati bergumam "Benar juga ya, dulu aku melakukan ini itu demi sosial media. Demi apa coba?" Hahaha.</p>
<p>Tentu saja facebook dan instagram adalah permulaan, target berikutnya adalah whatsapp.</p>
<p>Aku menulis ini bukan untuk mengajak kalian menghapus sosial media. Aku juga tidak membenci kalian pemakainya. Tapi mari renungkan bersama "Why do we do that?"</p>
<blockquote>
<p>If You're Not Paying for It; You're the Product -- QOTD</p>
</blockquote>
Install Pihole dan Dnscrypt-proxy di Container LXC
2019-09-16T17:22:59+07:00
2019-09-16T17:22:59+07:00
Unknown
https://www.sumarsono.com/install-pihole-dan-dnscrypt-proxy-di-container-lxc/
<p>PiHole sejak mendukung FTL jadi bisa pakai upstrean dnscrypt-proxy. Keren ya. Untuk yang belum tahu, pihole ini merupakan on-premise ads blocker. Kalian bisa bayangkan sebuah server yang jadi pusat untuk blokir iklan.
Pihole membklokir iklan di level DNS, dari sini kita sudah punya gambaran dengan memakai dns server yang dibuat pihole kita bisa akses internet dengan fitur ads blocker.
Ya tidak bisa dipungkiri, sebagian iklan di internet benar-benar mengesalkan. Mending di blokir aja.</p>
<p>Aku punya satu komputer yang bisa dikatan hampir tidak pernah mati. Jadi aku berencana menjadikan komputer itu sebagai server pihole dan dnscrypt-proxy. Komputer tsb sudah terpasang lxd, jadi aku berniat memasang pihole di container lxc. Langkahnya cukup sederhana:</p>
<ol>
<li>Bikin container pihole pakai image debian 9.</li>
<li>Install pihole dan bind port 53.</li>
<li>Install dnscrypt-proxy dan bind port 5454.</li>
<li>Ganti upstream pihole ke dnscrypt proxy yang kita install (127.0.0.1#5454)</li>
<li>Expose tcp port 53 dan udp port 53 dari container pihole ke luar pakai lxc device, supaya perangkat lain bisa memakai fasilitas pihole.</li>
<li>Set dns perangkat ke ip komputer yang terpasang pihole.</li>
</ol>
<p>Seperti itu ringkasnya, berikut ini kurang lebih prosesnya:</p>
<ol>
<li>Create container</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>lxc launch images:debian/stretch pihole
</span></code></pre>
<ol start="2">
<li>Install wget dan curl pada container pihole</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>lxc exec pihole -- apt update
</span><span>lxc exec pihole -- apt install wget curl -y
</span></code></pre>
<ol start="3">
<li>Install pihole pada container pihole</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>lxc exec pihole -- bash
</span><span>apt purge dnsmasq # conflict sama pihole, pihole membawa custom dnsmasq yg support ftl
</span><span>curl -sSL https://install.pi-hole.net | bash
</span></code></pre>
<ol start="4">
<li>Install dnscrypt-proxy</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>wget https://github.com/DNSCrypt/dnscrypt-proxy/releases/download/2.0.27/dnscrypt-proxy-linux_x86_64-2.0.27.tar.gz
</span><span>tar -xf dnscrypt-proxy-linux_x86_64-2.0.27.tar.gz
</span><span>cd linux-x86_64/
</span><span>cp example-dnscrypt-proxy.toml dnscrypt-proxy.toml
</span><span>vi dnscrypt-proxy.toml # edit port 53 menjadi 5454 biar tidak konflik dengan pihole
</span><span>./dnscrypt-proxy -service install # install systemd service untuk pihole-FTL
</span><span>./dnscrypt-proxy -service start # start service pihole-FTL
</span></code></pre>
<ol start="5">
<li>Ganti upstream pihole ke dnscrypt-proxy</li>
</ol>
<script async src="https://telegram.org/js/telegram-widget.js?7" data-telegram-post="unomindgithubio/51" data-width="100%"></script>
<ol start="6">
<li>Bikin proxy untuk expose port dns pihole</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>lxc config device add pihole piholetcp proxy listen=tcp:192.168.1.209:53 connect=tcp:127.0.0.1:53
</span><span>lxc config device add pihole piholeudp proxy listen=udp:192.168.1.209:53 connect=udp:127.0.0.1:53
</span></code></pre>
<ol start="7">
<li>Sisanya tinggal set perangkat
Set perangkat untuk pakai dns 192.168.1.209</li>
</ol>
<p>Selamat browsing++. Browsing bebas iklan plus dnscrypt.</p>
<p>Note:
saat install pihole, ada kendala, installnya gak bisa finish, tahu-tahu exit gitu aja. Check binary pihole juga gak kepasang.
Solusinya, install paket bc, aku tidak tahu fungsinya untuk apa. Referensinya di <a href="https://discourse.pi-hole.net/t/solved-bash-pihole-command-not-found/5028">forum pihole</a></p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>apt install bc -y
</span></code></pre>
Auto Start LXD Container
2019-09-07T07:54:07+07:00
2019-09-07T07:54:07+07:00
Unknown
https://www.sumarsono.com/auto-start-lxd-container/
<p>Bagaimana caranya supaya container LXD bisa auto start ketika mesin dinyalakan? sehingga kita tidak perlu menjalankan perintah <code>lxc start nama-container</code>.
Fitur <code>boot.autostart</code> adalah jawabannya. Berikut ini contohnya:</p>
<p>Saya punya container:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>» sudo lxc list
</span><span>+-----------+---------+-----------------------+----------------------------------------------+------------+-----------+
</span><span>| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
</span><span>+-----------+---------+-----------------------+----------------------------------------------+------------+-----------+
</span><span>| archlinux | STOPPED | | | PERSISTENT | 0 |
</span><span>+-----------+---------+-----------------------+----------------------------------------------+------------+-----------+
</span><span>| farm | STOPPED | | | PERSISTENT | 0 |
</span><span>+-----------+---------+-----------------------+----------------------------------------------+------------+-----------+
</span><span>| haproxy | RUNNING | 10.205.252.41 (eth0) | fd42:720:6748:f67b:216:3eff:fe22:1c8f (eth0) | PERSISTENT | 0 |
</span><span>+-----------+---------+-----------------------+----------------------------------------------+------------+-----------+
</span><span>| web2 | RUNNING | 10.205.252.216 (eth0) | fd42:720:6748:f67b:216:3eff:feee:6f0a (eth0) | PERSISTENT | 0 |
</span><span>+-----------+---------+-----------------------+----------------------------------------------+------------+-----------+
</span></code></pre>
<p>Saya ingin membuat haproxy autostart ketika mesin dinyalakan:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo lxc config set haproxy boot.autostart true
</span></code></pre>
<p>Selesai, kita bisa reboot komputer dan lihat hasilnya. Selain cara tadi, kita juga bisa langsung edit config haproxy kemudian menambahkan <code>boot.autostart: "true"</code>.
Mudah ya, semoga bermanfaat.</p>
Cara Backup LXD dan Restore ke Komputer lain
2019-09-04T01:04:13+07:00
2019-09-04T01:04:13+07:00
Unknown
https://www.sumarsono.com/cara-backup-lxd-dan-restore-ke-komputer-lain/
<p>Aku pernah bahas kalau aku jadinya pakai LXD versi snap di Manjaro. Sungguh berkah, snap memudahkan aku untuk backup dan restore lxd beserta kontainernya secara keseluruhan.</p>
<p>Pertama eksekusi perintah berikut:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>snap save lxd
</span></code></pre>
<p>Kedua, copy snapshot file dari /var/lib/snapd/snapshots ke mesin baru yang sudah diinstall snap.</p>
<p>Ketiga, di mesin baru eksekusi perintah ini:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>snap saved
</span></code></pre>
<p>Akan muncul daftar backup snap, contohnya seperti ini:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>▶ snap saved
</span><span>Set Snap Age Version Rev Size Notes
</span><span>1 hello-world 1d18h 6.4 29 251B auto
</span><span>4 lxd 1d17h 3.16 11727 2.82GB -
</span><span>
</span></code></pre>
<p>Kemudian restore backup tersebut dengan perintah:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>snap restore {id}
</span></code></pre>
<p>ganti <code>{id}</code> sesuai dengan list yang muncul, dalam kasus saya adalah 4.</p>
<p>Lanjut, restart service snap.lxd.daemon.unix.socket atau Bisa juga dengan restart mesin.</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>systemctl restart snap.lxd.daemon.unix.socket
</span></code></pre>
<p>Selesai, begitu saja. lxd beserta containernya udah jalan di mesin baru.</p>
Menjalankan Mariadb dalam LXD Container
2019-09-03T01:15:11+07:00
2019-09-03T01:15:11+07:00
Unknown
https://www.sumarsono.com/menjalankan-mariadb-dalam-lxd-container/
<p>Menjalankan mariadb dengan Docker container sudah hal yang umum, sangat sederhana, modal docker run. Beda lagi dengan menjalankan mariadb dalam lxd container karena harus install paket layaknya bare metal atau virtual machine. Yep, lxd container full OS, docker container per APP.</p>
<p>Launch lxd container ubuntu dan beri nama mariadb untuk container tersebut:
lxc launch ubuntu-18.04 mariadb</p>
<p>Kok imagenya ubuntu-18.04? bukan ubuntu:18.94 atau images:ubuntu? Itu karena sebelumnya saya sudah download image ubuntu, jadi sudah punya di lokal gak perlu ambil dari remote. Nah ubuntu-18.04 ini hanya alias.</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>lxc image list
</span><span>+--------------+--------------+--------+-----------------------------------------------+--------+----------+------------------------------+
</span><span>| ALIAS | FINGERPRINT | PUBLIC | DESCRIPTION | ARCH | SIZE | UPLOAD DATE |
</span><span>+--------------+--------------+--------+-----------------------------------------------+--------+----------+------------------------------+
</span><span>| archlinux | db7f17046b8d | no | Archlinux current amd64 (20190901_04:18) | x86_64 | 150.03MB | Sep 2, 2019 at 1:29am (UTC) |
</span><span>+--------------+--------------+--------+-----------------------------------------------+--------+----------+------------------------------+
</span><span>| ubuntu-18.04 | 2dd611e2689a | no | ubuntu 18.04 LTS amd64 (release) (20190813.1) | x86_64 | 177.60MB | Aug 31, 2019 at 4:51am (UTC) |
</span><span>+--------------+--------------+--------+-----------------------------------------------+--------+----------+------------------------------+
</span></code></pre>
<p>Setelah selesai launch, jika kita list container kita akan muncul nama mariadb:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>lxc list
</span><span>+------------+---------+-----------------------+-----------------------------------------------+------------+-----------+
</span><span>| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
</span><span>+------------+---------+-----------------------+-----------------------------------------------+------------+-----------+
</span><span>| haproxy | RUNNING | 10.174.126.81 (eth0) | fd42:deee:e13a:f247:216:3eff:feeb:91ea (eth0) | PERSISTENT | 0 |
</span><span>+------------+---------+-----------------------+-----------------------------------------------+------------+-----------+
</span><span>| mariadb | RUNNING | 10.174.126.147 (eth0) | fd42:deee:e13a:f247:216:3eff:fe84:d412 (eth0) | PERSISTENT | 0 |
</span><span>+------------+---------+-----------------------+-----------------------------------------------+------------+-----------+
</span></code></pre>
<p>Selanjutnya layaknya bare metal atau vm, lakukan update repo dan install mariadb:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>lxc exec mariadb -- apt update
</span></code></pre>
<p>Selesai update repo, kita install mariadb:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>lxc exec mariadb -- apt install mariadb-server
</span></code></pre>
<p>Jalankan mysql_secure_installation</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>lxc exec mariadb -- mysql_secure_installation
</span></code></pre>
<p>Oh ya, selain menggunakan lxc exec, kita juga bisa menggunakan lxc console untuk masuk ke console container, tapi kita harus bikin user dulu dengan cara</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>lxc exec mariadb -- adduser derp
</span></code></pre>
<p>Setelah itu silakan login ke console container mariadb dengan user derp</p>
<p>Seleasi, silakan lanjutkan ritual umum seperti securing mariadb, bikin user, bikin db, dst. Kalau ingin expose port mariadb keluar, silakan edit bind address mariadbnya kemudian gunakan lxd proxy sepert deijelaskan di artikelku [disini: expose port lxd container ke luar host]({% post_url 2019-09-02-expose-port-lxd-container %}).</p>
Expose Port LXD Container
2019-09-02T17:47:59+07:00
2019-09-02T17:47:59+07:00
Unknown
https://www.sumarsono.com/expose-port-lxd-container/
<p>Bagaiamana cara akses aplikasi yang ada di dalam LXD Container dari luar host? Bagaimana cara kita ssh ke dalam lxd container dari luar host? Caranya ada dua.
Yang petama adalah dengan iptables, yep kita bisa bikin rule PREROUTING dan DNAT.
Yang kedua, pakai fitur dari LXD namanya proxy device, dengan syarat LXD yang dipakai sudah versi 3.
Cara menggunakan iptables sudah sangat banyak dibahas, jadi aku hanya akan post cara pakai LXD proxy. Misal aku punya lxd container bernama haproxy, didalam container dia berjalan di port 80 dan 443.</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>lxc list
</span><span>+------------+---------+-----------------------+-----------------------------------------------+------------+-----------+
</span><span>| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
</span><span>+------------+---------+-----------------------+-----------------------------------------------+------------+-----------+
</span><span>+------------+---------+-----------------------+-----------------------------------------------+------------+-----------+
</span><span>| haproxy | RUNNING | 10.174.126.81 (eth0) | fd42:deee:e13a:f247:216:3eff:feeb:91ea (eth0) | PERSISTENT | 0 |
</span><span>+------------+---------+-----------------------+-----------------------------------------------+------------+-----------+
</span></code></pre>
<p>untuk expose port 80 dan 443 milik haproxy ke luar host, maka dari dalam host kita jalankan perintah berikut:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>lxc config device add haproxy myport80 proxy listen=tcp:0.0.0.0:80 connect=tcp:127.0.0.1:80
</span><span>lxc config device add haproxy myport443 proxy listen=tcp:0.0.0.0:443 connect=tcp:127.0.0.1:80
</span></code></pre>
<p>Jadi misal host ku ip-nya 192.168.1.3, maka jika aku buka browser di komputer lain dalam satu network dan buka ip host ku, akan diteruskan ke container haproxy, yang muncul di browser adalah konten dari haproxy.</p>
<p>Untuk ssh juga sama,</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>lxc config device add haproxy myssh proxy listen=tcp:0.0.0.0:33331 connect=tcp:127.0.0.1:22
</span></code></pre>
<p>Untuk setiap yang akses ip host dengan port 33331 akan diteruskan ke dalam container port 22. Jadi misal host ku ip-nya 192.168.1.3, maka jika menjalankan ssh user@192.168.1.3 -p33331 akan diteruskan ke dalam container haproxy port 22.</p>
<p>Sangat mudah ya, silakan dieksplore lagi di <a href="https://lxd.readthedocs.io/en/latest/containers/#type-proxy">dokumentasi lxd.</a></p>
Install LXD di Manjaro Linux dan Keluarga Arch Linux Lainnya
2019-08-31T19:35:50+07:00
2019-08-31T19:35:50+07:00
Unknown
https://www.sumarsono.com/install-lxd-di-manjaro-linux-dan-keluarga-arch-linux-lainnya/
<p>LXD adalah Daemon based on liblxc offering a REST API to manage containers. Intinya, LXD itu merupakan manager untuk container yang dalam hal ini LXC.</p>
<blockquote>
<blockquote>
<p>LXD is a next generation system container manager. It offers a user experience similar to virtual machines but using Linux containers instead.
It's image based with pre-made images available for a wide number of Linux distributions and is built around a very powerful, yet pretty simple, REST API.
To get a better idea of what LXD is and what it does, you can try it online! Then if you want to run it locally, take a look at our getting started guide.
The LXD project was founded and is currently led by Canonical Ltd with contributions from a range of other companies and individual contributors.</p>
</blockquote>
</blockquote>
<p>Selengkapnya di <a href="https://linuxcontainers.org/lxd/">linuxcontainers.org/</a></p>
<p>Dalam keluarga Arch Linux dan tururnannya, ketersediaan paket-paket sangat lengkap. Selain ada repo official, ada tambahan repo komunitas (AUR). Sayangnya, paket dalam aur tidak selalu bisa diinstall. Contohnya adalah ketika aku ingin memasang paket lxd dari aur, selalu ada galat. Pertama pakai aur helper bernama yay, gagal. Kedua manual pakai makepkg, gagal juga.
Sempat menyerah untuk install LXD, sampai akhirnya membuka repo LXD di github. LXD ada paket snap!.</p>
<h2 id="install-snapd">install snapd</h2>
<p>cukup mudah dan lurus saja, tidak ada kendala</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo pacman -S snapd
</span><span>sudo systemctl enable --now snapd
</span></code></pre>
<p>Reload session dengan cara keluar masuk terminal atau bisa juga manual export path si snapd.</p>
<h2 id="install-lxd">install lxd</h2>
<p>Ini juga mudah, tanpa kendala</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo snap install lxd
</span></code></pre>
<h2 id="konfigurasi-lxd">konfigurasi lxd</h2>
<p>Cukup satu perintah kemudian ikuti wizard</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo lxd init
</span></code></pre>
<h2 id="list-remote-image-lxd">list remote image lxd</h2>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo lxc image list images:
</span></code></pre>
<h2 id="launch-container-sesuai-image-yg-diinginkan">launch container sesuai image yg diinginkan</h2>
<p>Dalam hal ini aku mau pakai image arch linux untuk membuat container bernama archlinux</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo lxc launch images:archlinux/current/amd64 archlinux
</span></code></pre>
<h2 id="lihat-daftar-container">lihat daftar container</h2>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo lxc list
</span></code></pre>
<p>Outputnya begini kurang lebih:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>+-----------+---------+-----------------------+----------------------------------------------+------------+-----------+
</span><span>| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
</span><span>+-----------+---------+-----------------------+----------------------------------------------+------------+-----------+
</span><span>| archlinux | RUNNING | 10.205.252.69 (eth0) | fd42:720:6748:f67b:216:3eff:fe42:9767 (eth0) | PERSISTENT | 0 |
</span><span>+-----------+---------+-----------------------+----------------------------------------------+------------+-----------+
</span></code></pre>
<h2 id="masuk-ke-shell-container">masuk ke shell container</h2>
<p>Untuk melakukan berbagai hal dalam kontainer, kita harus masuk consolenya, misalnya mau update paket, install paket, dst.</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo lxc exec archlinux -- bash
</span></code></pre>
<p>Selesai, dilanjut lagi kapan-kapan.</p>
Upgrade ke Jekyll 4.0.0
2019-08-21T19:48:01+07:00
2019-08-21T19:48:01+07:00
Unknown
https://www.sumarsono.com/upgrade-ke-jekyll-4-0-0/
<p><a href="https://jekyllrb.com/news/2019/08/20/jekyll-4-0-0-released/">Jekyll 4.0.0 rilis !</a></p>
<p>Caraku upgrade:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>cd /penyimpananBersama/nalakawula.github.io
</span><span>rm -rf Gemfile.lock
</span><span>gem update jekyll
</span><span>bundle install
</span></code></pre>
<p>Perhatikan output berikut:
{% raw %}</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>-------------------------------------------------------------------------------------
</span><span>Jekyll 4.0 comes with some major changes, notably:
</span><span>
</span><span> * Our `link` tag now comes with the `relative_url` filter incorporated into it.
</span><span> You should no longer prepend `{{ site.baseurl }}` to `{% link foo.md %}`
</span><span> For further details: https://github.com/jekyll/jekyll/pull/6727
</span><span>
</span><span> * Our `post_url` tag now comes with the `relative_url` filter incorporated into it.
</span><span> You shouldn't prepend `{{ site.baseurl }}` to `{% post_url 2019-03-27-hello %}`
</span><span> For further details: https://github.com/jekyll/jekyll/pull/7589
</span><span>
</span><span> * Support for deprecated configuration options has been removed. We will no longer
</span><span> output a warning and gracefully assign their values to the newer counterparts
</span><span> internally.
</span><span>-------------------------------------------------------------------------------------
</span></code></pre>
<p>{% endraw %}</p>
<p>kemudian Aku search dan replace tag <code>link</code> dan tag <code>post_url</code> untuk menyesuaikan dengan keterangan tersebut. Selanjutnya kau tes di lokal pakai <code>bundle exec jekyll serve</code>. Stelah oke baru deh push ke repo.</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>git add .
</span><span>git commit -m "upgrade ke jekyll 4.0.0"
</span><span>git push
</span></code></pre>
<p>Sisanya serahkan ke netlify, berikut contoh log-nya:
{% raw %}</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>7:41:34 PM: Fetching gem metadata from https://rubygems.org/
</span><span>7:41:34 PM: .
</span><span>7:41:34 PM: Resolving dependencies...
</span><span>7:41:34 PM: Using public_suffix 3.1.1
</span><span>7:41:34 PM: Using addressable 2.6.0
</span><span>7:41:34 PM: Using bundler 2.0.1
</span><span>7:41:34 PM: Using colorator 1.1.0
</span><span>7:41:34 PM: Using concurrent-ruby 1.1.5
</span><span>7:41:34 PM: Using eventmachine 1.2.7
</span><span>7:41:34 PM: Using http_parser.rb 0.6.0
</span><span>7:41:34 PM: Using em-websocket 0.5.1
</span><span>7:41:34 PM: Using ffi 1.11.1
</span><span>7:41:34 PM: Using forwardable-extended 2.6.0
</span><span>7:41:34 PM: Using i18n 1.6.0
</span><span>7:41:34 PM: Fetching sassc 2.1.0 (x86_64-linux)
</span><span>7:41:35 PM: Installing sassc 2.1.0 (x86_64-linux)
</span><span>7:41:35 PM: Fetching jekyll-sass-converter 2.0.0
</span><span>7:41:35 PM: Installing jekyll-sass-converter 2.0.0
</span><span>7:41:35 PM: Using rb-fsevent 0.10.3
</span><span>7:41:35 PM: Using rb-inotify 0.10.0
</span><span>7:41:35 PM: Using ruby_dep 1.5.0
</span><span>7:41:35 PM: Using listen 3.1.5
</span><span>7:41:35 PM: Using jekyll-watch 2.2.1
</span><span>7:41:35 PM: Using kramdown 2.1.0
</span><span>7:41:35 PM: Using kramdown-parser-gfm 1.1.0
</span><span>7:41:35 PM: Using liquid 4.0.3
</span><span>7:41:35 PM: Using mercenary 0.3.6
</span><span>7:41:35 PM: Using pathutil 0.16.2
</span><span>7:41:35 PM: Fetching rouge 3.9.0
</span><span>7:41:35 PM: Installing rouge 3.9.0
</span><span>7:41:36 PM: Using safe_yaml 1.0.5
</span><span>7:41:36 PM: Fetching unicode-display_width 1.6.0
</span><span>7:41:36 PM: Installing unicode-display_width 1.6.0
</span><span>7:41:36 PM: Fetching terminal-table 1.8.0
</span><span>7:41:36 PM: Installing terminal-table 1.8.0
</span><span>7:41:36 PM: Fetching jekyll 4.0.0
</span><span>7:41:36 PM: Installing jekyll 4.0.0
</span><span>7:41:36 PM: Using jekyll-archives 2.2.1
</span><span>7:41:36 PM: Using jekyll-feed 0.12.1
</span><span>7:41:36 PM: Using jekyll-paginate 1.1.0
</span><span>7:41:36 PM: Using jekyll-seo-tag 2.6.1
</span><span>7:41:36 PM: Using jekyll-sitemap 1.3.1
</span><span>7:41:36 PM: Bundle complete! 7 Gemfile dependencies, 33 gems now installed.
</span><span>7:41:36 PM: Bundled gems are installed into `/opt/build/cache/bundle`
</span><span>7:41:36 PM: Post-install message from jekyll:
</span><span>7:41:36 PM: -------------------------------------------------------------------------------------
</span><span>7:41:36 PM: Jekyll 4.0 comes with some major changes, notably:
</span><span>7:41:36 PM: * Our `link` tag now comes with the `relative_url` filter incorporated into it.
</span><span>7:41:36 PM: You should no longer prepend `{{ site.baseurl }}` to `{% link foo.md %}`
</span><span>7:41:36 PM: For further details: https://github.com/jekyll/jekyll/pull/6727
</span><span>7:41:36 PM: * Our `post_url` tag now comes with the `relative_url` filter incorporated into it.
</span><span>7:41:36 PM: You shouldn't prepend `{{ site.baseurl }}` to `{% post_url 2019-03-27-hello %}`
</span><span>7:41:36 PM: For further details: https://github.com/jekyll/jekyll/pull/7589
</span><span>7:41:36 PM: * Support for deprecated configuration options has been removed. We will no longer
</span><span>7:41:36 PM: output a warning and gracefully assign their values to the newer counterparts
</span><span>7:41:36 PM: internally.
</span><span>7:41:36 PM: -------------------------------------------------------------------------------------
</span><span>7:41:36 PM: Gem bundle installed
</span><span>7:41:36 PM: Started restoring cached go cache
</span><span>7:41:36 PM: Finished restoring cached go cache
</span><span>7:41:36 PM: unset GOOS;
</span><span>7:41:36 PM: unset GOARCH;
</span><span>7:41:36 PM: export GOROOT='/opt/buildhome/.gimme/versions/go1.12.linux.amd64';
</span><span>7:41:36 PM: export PATH="/opt/buildhome/.gimme/versions/go1.12.linux.amd64/bin:${PATH}";
</span><span>7:41:36 PM: go version >&2;
</span><span>7:41:36 PM: export GIMME_ENV='/opt/buildhome/.gimme/env/go1.12.linux.amd64.env';
</span><span>7:41:36 PM: go version go1.12 linux/amd64
</span><span>7:41:36 PM: Installing missing commands
</span><span>7:41:36 PM: Verify run directory
</span><span>7:41:36 PM: Executing user command: bundle exec jekyll build --config _config.sumarsono.com.yml
</span><span>7:41:37 PM: Configuration file: /opt/build/repo/_config.sumarsono.com.yml
</span><span>7:41:37 PM: Source: /opt/build/repo
</span><span>7:41:37 PM: Destination: /opt/build/repo/_site
</span><span>7:41:37 PM: Incremental build: disabled. Enable with --incremental
</span><span>7:41:37 PM: Generating...
</span><span>7:41:38 PM: Jekyll Feed: Generating feed for posts
</span><span>7:41:40 PM: done in 2.796 seconds.
</span><span>7:41:40 PM: Auto-regeneration: disabled. Use --watch to enable.
</span><span>7:41:40 PM: Skipping functions preparation step: no functions directory set
</span><span>7:41:40 PM: Caching artifacts
</span><span>7:41:40 PM: Started saving ruby gems
</span><span>7:41:40 PM: Finished saving ruby gems
</span><span>7:41:40 PM: Started saving pip cache
</span><span>7:41:40 PM: Finished saving pip cache
</span><span>7:41:40 PM: Started saving emacs cask dependencies
</span><span>7:41:40 PM: Finished saving emacs cask dependencies
</span><span>7:41:40 PM: Started saving maven dependencies
</span><span>7:41:40 PM: Finished saving maven dependencies
</span><span>7:41:40 PM: Started saving boot dependencies
</span><span>7:41:40 PM: Finished saving boot dependencies
</span><span>7:41:40 PM: Started saving go dependencies
</span><span>7:41:40 PM: Finished saving go dependencies
</span><span>7:41:40 PM: Build script success
</span><span>7:41:40 PM: Starting to deploy site from '_site'
</span><span>7:41:40 PM: Creating deploy tree
</span><span>7:41:41 PM: 134 new files to upload
</span><span>7:41:41 PM: 0 new functions to upload
</span><span>7:41:46 PM: Starting post processing
</span><span>7:41:46 PM: Minifying bundle
</span><span>7:41:49 PM: Minifying bundle
</span><span>7:42:09 PM: Finished processing build request in 53.173578981s
</span><span>7:42:18 PM: Post processing done
</span><span>7:42:18 PM: Site is live
</span></code></pre>
<p>{% endraw %}</p>
<p>Selesai</p>
Hosting Website di Rumah
2019-08-18T13:31:03+07:00
2019-08-18T13:31:03+07:00
Unknown
https://www.sumarsono.com/hosting-website-di-rumah/
<p>Hosting website di rumah? Memang bisa? Bisa dong dengan cara memanfaatkan dynamic dns dan port forwarding. Artikel kali ini akan membahas cara hosting website di rumah dan dapat diakses dari manapun dengan domain.</p>
<p>Syarat hosting website apa saja?</p>
<ol>
<li>Web server, aku akan pakai nginx untuk contoh.</li>
<li>IP address public dari ISP, nanti akan aku pakai untuk A record domain. Disini aku pakai ISP Indihome.</li>
<li>Domain, biar kita bisa akses website kita pakai nama, gak hafalan IP. Disini aku pakai subdomain laptop.sumarsono.com untuk demo.</li>
</ol>
<p>Masalahnya adalah ISP untuk rumahan tidak memberikan IP address public static (kecuali kita beli). IP Address yang berubah-ubah tentu merepotkan kita, masa iya setiap kita mau akses website kita harus cek public IP, kalau di rumah mah enak tinggal cek aja, lah kalau kita lagi di luar kota? Repot. Disini kita butuh yang namanya DDNS (Dynamic DNS), DNS dengan record yang dinamis. Kita juga butuh port forward dari router untuk forward port 80/443 dari luar ke web server.</p>
<p>Aku beli domain <a href="http://sumarsono.com">sumarsono.com</a> di <a href="https://namecheap.com">namecheap.com</a>. Dari namecheap aku dapat fitur free ddns. Untuk mengaktifkan ddns di namecheap, kita hanya perlu login ke dashboard kemudian masuk ke menu advance, cari dynamic dns dan aktifkan, catat password yang muncul karena akan kita pakai. Lihat gambar berikut:</p>
<p><img src="/assets/images/aktivasi-ddns-namecheap.webp" alt="gh-webhook.webp" /></p>
<p>Kemudian tambahkan A record denga ketentuan:</p>
<ul>
<li>Type: A record+Dynamic DNS Record</li>
<li>Host: laptop</li>
<li>Value: 127.0.0.1 (ini dummy aja gpp, nantinya akan otomatis berubah sesuai dengan IP public yang kita dapat dari ISP)</li>
</ul>
<p>Konfigurasi DDNS di namecheap sudah selesai, selanjutnya menyiapkan web server dan dynamic dns client. Dalam demo ini aku pakai laptop dengan OS Manjaro, untuk distro linux lain silakan menyesuaikan. Pertama kita install paket yang dibutuhkan:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo pacman -Syy nginx ddclient
</span></code></pre>
<p>Selanjutnya kita konfigurasi ddclient:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo nano /etc/ddclient/ddclient.conf
</span><span>
</span><span># tambahkan konfigurasi berikut ini:
</span><span>
</span><span>##
</span><span>## NameCheap (namecheap.com)
</span><span>##
</span><span> use=web, web=dynamicdns.park-your-domain.com/getip
</span><span> protocol=namecheap, \
</span><span> server=dynamicdns.park-your-domain.com, \
</span><span> login=sumarsono.com, \
</span><span> password=password-ddns-dari-namecheap \
</span><span> laptop
</span></code></pre>
<p>Keterangan:</p>
<p>yang perlu kalian sesuaikan adalah <code>login</code>, <code>password</code>, dan <code>laptop</code>. <code>laptop</code> disini adalah subdomain yang akan aku pakai, yang tadi sudah di set di namecheap.</p>
<p>Untuk nginx tidak akan saya konfigurasi karena cuma demo yang penting jalan.</p>
<p>Langkah selanjutnya adalah enable ddclient dan nginx:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo systemctl enable --now nginx
</span><span>sudo systemctl enable --now ddclient
</span></code></pre>
<p>Kemudian cek ip dari laptop.sumarsono.com apakah sudah sama dengan public ip dari isp (disini ip 127.0.0.1 yang tadi kita masukan mestinya sudah berubah jadi ip public isp)</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>drill laptop.sumarsono.com
</span><span>curl ifconfig.co
</span></code></pre>
<p>Langkah terakhir, aktifkan port forwarding di router. HTTP selalu 80, dan HTTPS selalu 443.
Login ke router indihome, masuk menu Forward Rules > Port Mapping Configurations, klik tombol new. Buat konfigurasi seperti gambar berikut:</p>
<p><img src="/assets/images/indihome-port-forwarding.webp" alt="gh-webhook.webp" /></p>
<p>Keterangan:</p>
<ul>
<li>internal host: IP addr laptop yang ada nginx nya</li>
<li>Protocol: TCP</li>
<li>Port: 80 untuk http dan 443 untuk https</li>
</ul>
<p>Kalau sudah beres semua, tinggal cek deh. Ini aku coba cek dari HP pakai koneksi Indosat:
<img src="/assets/images/laptop.sumarsono.com.webp" alt="gh-webhook.webp" /></p>
<p>Selesai.</p>
Menambahkan Tombol Back To Top pada Jekyll
2019-08-16T10:41:15+07:00
2019-08-16T10:41:15+07:00
Unknown
https://www.sumarsono.com/menambahkan-tombol-back-to-top-pada-jekyll/
<p>Untuk memudahkan scroll ke paling atas pada artikel yang panjang, aku butuh satu tombol back to top. Tadinya mau bikin pakai cara manual, tapi aku urungkan karena ketemu repo <a href="https://github.com/vfeskov/vanilla-back-to-top">vanilla-back-to-top</a>. Berikut ini deskripsinya: Simple and tiny Back To Top button with no dependencies. Hides when on top, scrolls up smoothly when clicked. Works equally great with Vue, React, Angular and without frameworks on Jekyll, Hugo and Hexo. Keren!</p>
<p>Akhirnya aku coba dengan cara edit <code>_layouts/default.html</code>, kemudian sebelum tag <code></body></code> aku tambahkan:</p>
<pre data-lang="html" style="background-color:#fcf0ca;color:#282828aa;" class="language-html "><code class="language-html" data-lang="html"><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">script </span><span style="color:#407959;">src=</span><span style="color:#79740e;">"https://unpkg.com/vanilla-back-to-top@7.2.0/dist/vanilla-back-to-top.min.js"</span><span style="color:#076678;">></</span><span style="font-weight:bold;color:#407959;">script</span><span style="color:#076678;">>
</span><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">script</span><span style="color:#076678;">></span><span style="color:#282828;">addBackToTop({
</span><span style="color:#282828;"> diameter: </span><span style="color:#8f3f71;">40</span><span style="color:#282828;">,
</span><span style="color:#282828;"> backgroundColor: </span><span style="color:#79740e;">'rgb(255, 82, 82)'</span><span style="color:#282828;">,
</span><span style="color:#282828;"> textColor: </span><span style="color:#79740e;">'#fff'
</span><span style="color:#282828;">})</span><span style="color:#076678;"></</span><span style="font-weight:bold;color:#407959;">script</span><span style="color:#076678;">>
</span></code></pre>
<p>Tes pakai <code>bundle exec jekyll serve</code> hasilnya memuaskan, akhirnya saya push ke repo produksi.</p>
Test comments.app
2019-08-14T18:40:40+07:00
2019-08-14T18:40:40+07:00
Unknown
https://www.sumarsono.com/test-comments-app/
<p>Sejujurnya aku kurang sreg menggunakan disquss, entah kenapa. Oleh sebab itu, aku mencoba menggunakan comments-app. Bagiku ini menarik karena terhubung dengan telegram. comments.app terlihat lebih sederhana, tidak ribet, tinggal embed. Aku ingin lihat apakah comments.app ini akan memenuhi kebutuhanku.</p>
Blokir Halus Visitor Web dari Luar Indonesia
2019-05-21T19:12:01+07:00
2019-05-21T19:12:01+07:00
Unknown
https://www.sumarsono.com/blokir-halus-visitor-web-dari-luar-indonesia/
<p>Blokir halus? apaan dah. Haha. Saya tidak tahu padanan kata untuk <em>soft block</em> XD</p>
<p>Jadi begini, saya ingin pengunjung website saya hanya berasal dari Indonesia. Selain pengunjung dari Indonesia akan diberi <em>challenge</em> berupa reCaptcha. <em>Challenge</em> inilah yg kusebut blokir halus. Hehe.</p>
<p>Nah, website ini kan <em>serverless</em> saya nebeng di github pages dan netlify, jadi mustahil untuk setting dari sisi server. Solusinya, saya pakai fitur firewall dari cloudflare.</p>
<p>Saya buat rule firewall (max 5 rule untuk versi gratis XD) <code>(not ip.geoip.country in {"ID"})</code> seperti gambar berikut:</p>
<script async src="https://telegram.org/js/telegram-widget.js?5" data-telegram-post="unomindgithubio/47" data-width="100%"></script>
<p>Hasilnya, jika kita simulasikan dengan bantuan <a href="https://www.locabrowser.com/">localbrowser</a> adalah sebagai berikut:</p>
<script async src="https://telegram.org/js/telegram-widget.js?5" data-telegram-post="unomindgithubio/48" data-width="100%"></script>
<p>Selanjutnya di log firewall cloudflare akan nampak seperti berikut:</p>
<script async src="https://telegram.org/js/telegram-widget.js?5" data-telegram-post="unomindgithubio/49" data-width="100%"></script>
<p>Akhirnya, semua visitor selain dari Indonesia akan disuguhi reCaptcha. Semoga bermanfaat.</p>
Manjaroku kacau, begini ceritanya
2019-05-20T18:58:07+07:00
2019-05-20T18:58:07+07:00
Unknown
https://www.sumarsono.com/manjaroku-kacau-begini-ceritanya/
<p>Saya pakai Manjaro edisi budgie. So far so good, sampai ada major update. Setelah ku update jadi kacau. Setiap kali saya tancep flashdisk/hdd ext/HP Android, selalu autorun VSCode. Mengganggu banget dan jelas gk beres.</p>
<p>Akhirnya saya tanya ke group telegram Manjaro Indonesia, disana ada yang memberi solusi. Nah, yang saya lakukan adalah:</p>
<ol>
<li>
<p>Edit file <code>/usr/share/applications/mimeinfo.cache</code>
Cari baris:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>inode/directory=visual-studio-code.desktop;org.gnome.Nautilus.desktop;
</span></code></pre>
<p>Ubah menjadi</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>inode/directory=org.gnome.Nautilus.desktop;visual-studio-code.desktop;
</span></code></pre>
</li>
<li>
<p>Edit file <code>~/.config/mimeapps.list</code>, tambahkan baris:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>inode/directory=org.gnome.Nautilus.desktop;
</span></code></pre>
</li>
</ol>
<p>Setelah saya reboot, dan tes, solved.</p>
Membuat Penyimpanan Bersama Untuk Pengguna dalam Mesin Linux
2019-05-12T07:33:56+07:00
2019-05-12T07:33:56+07:00
Unknown
https://www.sumarsono.com/membuat-penyimpanan-bersama-untuk-pengguna-dalam-mesin-linux/
<p>Satu mesin linux bisa berisi banyak pengguna, misalnya budi, dodi, dan nino. Masing-masing pengguna mempunyai home directory sendiri-sendiri.
Ada kalanya, kita butuh penyimpanan bersama. Maksud dar penyimpanan bersama adalah suatu direktori yang setiap pengguna memiliki iji baca, tulis, dan eksekusi. Contohnya jika budi, dodi, dan nino adalah web developer yang butuh ijin baca tulis sebuah direktori proyek.</p>
<p>Di linux, mengatur ACL seperti itu sangat mudah. Strategi yang bisa dipilih adalah dengan cara memasukan budi, dodi, dan nino kedalam satu common group. Langsung praktek saja:</p>
<p>Pertama buat direktori <code>/penyimpananBersama</code></p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">sudo mkdir /penyimpananBersama
</span></code></pre>
<p>Bikin direktori kok pakai sudo? krn bikinnya di <code>/</code></p>
<p>Kedua, buat group <code>bersama</code></p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">sudo groupadd bersama
</span></code></pre>
<p>Ketiga, assign group <code>bersama</code> ke direktori <code>/penyimpananBersama</code></p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">sudo chgrp bersama /penyimpananBersama
</span></code></pre>
<p>Keempat, edit akses kontrol direktori <code>/penyimpananBersama</code> supaya yang berada dalam group bisa rwx</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">sudo chmod 2775 /penyimpananBersama
</span></code></pre>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>2: sgid (set group ID) supaya kedepan jika dibuat file/folder baru groupnya akan mengikuti parent.
</span><span>7: Owner RWX
</span><span>7: Group RWX
</span><span>5: Other R-X
</span></code></pre>
<p>Kelima, assign budi, dodi, dan nino ke dalam group <code>bersama</code></p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo usermod -aG bersama budi
</span><span>sudo usermod -aG bersama dodi
</span><span>sudo usermod -aG bersama nino
</span></code></pre>
<p>Silakan login dengan masing-masing user tsb, sudah bisa dipastikan bisa melakukan baca/tulis di direktori <code>/penyimpananBersama</code>.</p>
<p>Kesimpulannya, setiap user yang menjadi anggota group <code>bersama</code> akan mendapat hak akses yang sama pada direktori <code>/penyimpananBersama</code>.</p>
Systemd Timer - Caraku Melakukan Otomasi Proses Pengiriman Log Pekerjaan Harian
2019-05-03T13:18:39+07:00
2019-05-03T13:18:39+07:00
Unknown
https://www.sumarsono.com/systemd-timer-caraku-melakukan-otomasi-proses-pengiriman-log-pekerjaan-harian/
<p>Yo..haha. Artikel sebelum ini, saya sudah tulis bagaiaman caraku mengirirm log pekerjaan secara otomatis dengan bantuan cron.
Setelah menulis artikel kemarin, saya jadi punya ide untuk menulis lagi, topiknya sama dengan kemarin, hanya saja kali ini tidak pakai cron.
Yes, jaman systemd, kita pakai systemd timer.</p>
<p>Untuk versi systemd timer, bakal lebih panjang flownya. Kita butuh:</p>
<ol>
<li>generateJobLog.sh</li>
<li>kirimJobLog.sh</li>
<li>generateJobLog.timer</li>
<li>generateJobLog.service</li>
<li>kirimJobLog.timer</li>
<li>kirimJobLog.service</li>
</ol>
<p>Kalau sudah ready semua, tinggal enable timernya. And let the system do the rest.
Contoh setelah aktif:</p>
<script async src="https://telegram.org/js/telegram-widget.js?5" data-telegram-post="unomindgithubio/46" data-width="100%"></script>
<p>Untuk contoh file diatas, saya masukan ke satu gist saja biar praktis. <a href="https://gist.github.com/unomind/77f449bef2958b5750460975864094b3">Check this out</a></p>
Caraku Melakukan Otomasi Proses Pengiriman Log Pekerjaan Harian
2019-05-02T15:51:23+07:00
2019-05-02T15:51:23+07:00
Unknown
https://www.sumarsono.com/caraku-melakukan-otomasi-proses-pengiriman-log-pekerjaan-harian/
<p>Di tempat kerjaku sekarang, setiap hari harus mengirim Log pekerjaan tepat jam 5 sore. Membosankan sih, kalau setiap hari harus membuka gmail, menulis alamat email yang sama, menulis subject yg sekuensial, dan klik tombol kirim.
Serius, itu pengulangan yang membosankan, awal jalan 1 minggu aja dah bikin bosan. Waktu yg dikonsumsi untuk perulangan bisa kupakai untuk hal lain.</p>
<p>Kenapa tidak kita otomasi saja? jadi kita fokus nulis body emailnya aja. Yeah, ku realisasikan, begini step-nya:</p>
<ul>
<li>Setup msmtp pakai email kantor.</li>
<li>Set msmtp sbg alias sendmail.</li>
<li>Bikin bash script untuk generate template email harian:</li>
</ul>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="font-style:italic;color:#928374;">#!/usr/bin/bash
</span><span style="color:#b57614;">printf </span><span style="color:#79740e;">"From:sensordemiprivasi@sensor.com\nSubject:Log Pekerjaan $(</span><span style="color:#282828;">date +%Y-%m-%d</span><span style="color:#79740e;">)\n\nSumarsono\nSysadmin\n\n1. " </span><span style="color:#b23c15;">></span><span style="color:#282828;"> /home/sumarsono/Sumarsono/Log-Pekerjaan-$(date +%Y%m%d)
</span></code></pre>
<ul>
<li>Bikin bash script untuk send email harian:</li>
</ul>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="font-style:italic;color:#928374;">#!/usr/bin/bash
</span><span style="color:#282828;">cat /home/sumarsono/Sumarsono/Log-Pekerjaan-$(date +%Y%m%d) </span><span style="color:#b23c15;">| </span><span style="color:#282828;">msmtp -a default hrd@sensor.com,sensor@sensor.com
</span></code></pre>
<ul>
<li>Bikin crontab buat eksekusi dua script tadi, generate template email setiap jam 9 pagi. Kemudian kirim email tiap jam 17.</li>
</ul>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>0 9 * * * /usr/bin/bash /home/sumarsono/Sumarsono/sumar-bash/generateMail.sh
</span><span>0 17 * * * /usr/bin/bash /home/sumarsono/Sumarsono/sumar-bash/sendMail.sh
</span></code></pre>
<blockquote>
<p>Tips! Kalian bisa generate cron di crontab.guru</p>
</blockquote>
<ul>
<li>Selesai. </li>
</ul>
<p>Jadi ya daily task bisa dimasukin ke template, terus saya fokus ngisi body email dengan task-task yg kukerjakan hari itu. Jam 17.00 sistem secara otomatis mengirim email.</p>
Mengunjungi Negeri Atas Awan
2019-04-30T10:12:10+07:00
2019-04-30T10:12:10+07:00
Unknown
https://www.sumarsono.com/mengunjungi-negeri-atas-awan/
<p>26 April 2019, saya mengunjungi negeri atas awan, negeri atas awan yg kumaksud adalah Dieng. Yaps, sudut negeri yg terkenal akan keberadaan anak gimbalnya. Saya tidak mau cerita banyak sih, hanya ingin mengajak kalian "Ayo mampir kesana!". </p>
<p>Murah, biaya parkir mobil 5rb, tiket masuk tempat wisata 15rb, makan nasi+sayur+tempe kemul+teh anget 12rb, dan biaya penginapan 150rb per kamar. Jadi, ayo kesana!.</p>
<p>Foto-foto dibawah ini memang kurang menarik krn saya tidak jago jepret-jepret. Tempat aslinya sungguh menarik, dingin (saking dinginnya pas lu cebok rasanya ngilu), segar, fresh. Te O Pe Be Ge Te !.</p>
<script async src="https://telegram.org/js/telegram-widget.js?5" data-telegram-post="unomindgithubio/44" data-width="100%"></script>
<script async src="https://telegram.org/js/telegram-widget.js?5" data-telegram-post="unomindgithubio/34" data-width="100%"></script>
Jekyll - Embed Google Form
2019-04-26T14:10:00+07:00
2019-04-26T14:10:00+07:00
Unknown
https://www.sumarsono.com/jekyll-embed-google-form/
<p>Embed google form ke jekyll mah tinggal embed aja, haha. Kalau tampilannya mau ikut tampilan si google form. Ini bisa jadi solusi kere hore untuk kebutuhan form di static site.</p>
<p>Nah, kalau tampilannya mau custom sesuka kita? Begini caranya.</p>
<p>tldr:
Intinya kalau kita mau membuat custom form dari google form, kita butuh form action dari google form dan value dari name yg ada di kolom google form.</p>
<h2 id="1-buat-google-form">1. Buat google form</h2>
<p>Setelah selesai membuat form, dapatkan linknya. Contohnya saya membuat form yang isinya short text dan paragraph</p>
<script async src="https://telegram.org/js/telegram-widget.js?5" data-telegram-post="unomindgithubio/26" data-width="100%"></script>
<h2 id="2-buka-link-tsb-di-browser-lain">2. Buka link tsb di browser lain</h2>
<p>Setelah terbuka, lakukan inspect element. Tujuan inpect element adalah untuk mendapatkan <code>name</code> dari kolom-kolom yang ada dalam form, dan untuk mendapatkan <code>form action</code>.</p>
<p>Dari form yg saya buat, saya butuh:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>- `name` dari `<input>`
</span><span>- `name` dari <textarea>
</span><span>- link `action` dari form
</span></code></pre>
<p>Tiga hal tadi harus di copy dan dicatat, akan dipakai nanti</p>
<p>Contoh mendapatkan name dari kolom nama:</p>
<script async src="https://telegram.org/js/telegram-widget.js?5" data-telegram-post="unomindgithubio/27" data-width="100%"></script>
<p>Contoh mendapatkan action dari form:</p>
<script async src="https://telegram.org/js/telegram-widget.js?5" data-telegram-post="unomindgithubio/28" data-width="100%"></script>
<h2 id="3-bikin-custom-form">3. Bikin custom form</h2>
<p>Saya bikin contoh sederhana:</p>
<p>Komponen ini diambil dari google form:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>action="https://docs.google.com/forms/d/e/1FAIpQLSf_iYsRa5FoIw5hv6edHvmwpdIqybga0xZcu_JF-qG4NkD5cg/formResponse"
</span><span>name="entry.1319304330"
</span><span>name="entry.1931495421"
</span></code></pre>
<p>html</p>
<pre data-lang="html" style="background-color:#fcf0ca;color:#282828aa;" class="language-html "><code class="language-html" data-lang="html"><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">div </span><span style="color:#407959;">class=</span><span style="color:#79740e;">"container"</span><span style="color:#076678;">>
</span><span> </span><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">form </span><span style="color:#79740e;">id</span><span style="color:#407959;">=</span><span style="color:#79740e;">"contact" </span><span style="color:#407959;">action=</span><span style="color:#79740e;">"https://docs.google.com/forms/d/e/1FAIpQLSf_iYsRa5FoIw5hv6edHvmwpdIqybga0xZcu_JF-qG4NkD5cg/formResponse" </span><span style="color:#407959;">method=</span><span style="color:#79740e;">"post"</span><span style="color:#076678;">>
</span><span> </span><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">h3</span><span style="color:#076678;">></span><span>Saran/Masukan/Kritik</span><span style="color:#076678;"></</span><span style="font-weight:bold;color:#407959;">h3</span><span style="color:#076678;">>
</span><span> </span><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">h4</span><span style="color:#076678;">></span><span>Sampaikan biar kamu plong</span><span style="color:#076678;"></</span><span style="font-weight:bold;color:#407959;">h4</span><span style="color:#076678;">>
</span><span> </span><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">fieldset</span><span style="color:#076678;">>
</span><span> </span><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">input </span><span style="color:#407959;">placeholder=</span><span style="color:#79740e;">"Nama kamu (isi sembarang kalau kamu sungkan)" </span><span style="color:#407959;">type=</span><span style="color:#79740e;">"text" </span><span style="color:#407959;">tabindex=</span><span style="color:#79740e;">"1" </span><span style="color:#407959;">name=</span><span style="color:#79740e;">"entry.1319304330" </span><span style="color:#407959;">required autofocus</span><span style="color:#076678;">>
</span><span> </span><span style="color:#076678;"></</span><span style="font-weight:bold;color:#407959;">fieldset</span><span style="color:#076678;">>
</span><span> </span><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">fieldset</span><span style="color:#076678;">>
</span><span> </span><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">textarea </span><span style="color:#407959;">placeholder=</span><span style="color:#79740e;">"Tulis saran/masukan/kritik kamu disini" </span><span style="color:#407959;">tabindex=</span><span style="color:#79740e;">"5" </span><span style="color:#407959;">name=</span><span style="color:#79740e;">"entry.1931495421" </span><span style="color:#407959;">required</span><span style="color:#076678;">></</span><span style="font-weight:bold;color:#407959;">textarea</span><span style="color:#076678;">>
</span><span> </span><span style="color:#076678;"></</span><span style="font-weight:bold;color:#407959;">fieldset</span><span style="color:#076678;">>
</span><span> </span><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">fieldset</span><span style="color:#076678;">>
</span><span> </span><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">button </span><span style="color:#407959;">name=</span><span style="color:#79740e;">"submit" </span><span style="color:#407959;">type=</span><span style="color:#79740e;">"submit" id</span><span style="color:#407959;">=</span><span style="color:#79740e;">"contact-submit" </span><span style="color:#407959;">data-submit=</span><span style="color:#79740e;">"...Sending"</span><span style="color:#076678;">></span><span>Kirim</span><span style="color:#076678;"></</span><span style="font-weight:bold;color:#407959;">button</span><span style="color:#076678;">>
</span><span> </span><span style="color:#076678;"></</span><span style="font-weight:bold;color:#407959;">fieldset</span><span style="color:#076678;">>
</span><span> </span><span style="color:#076678;"></</span><span style="font-weight:bold;color:#407959;">form</span><span style="color:#076678;">>
</span><span style="color:#076678;"></</span><span style="font-weight:bold;color:#407959;">div</span><span style="color:#076678;">>
</span></code></pre>
<p>css</p>
<pre data-lang="css" style="background-color:#fcf0ca;color:#282828aa;" class="language-css "><code class="language-css" data-lang="css"><span style="color:#9d0006;">@import </span><span style="color:#b57614;">url</span><span style="color:#282828;">(</span><span style="color:#79740e;">https://fonts.googleapis.com/css?family=Roboto:400,300,600,400italic</span><span style="color:#282828;">)</span><span>;
</span><span style="font-weight:bold;color:#9d0006;">* </span><span>{
</span><span> </span><span style="color:#407959;">margin</span><span>: </span><span style="color:#b57614;">0</span><span>;
</span><span> </span><span style="color:#407959;">padding</span><span>: </span><span style="color:#b57614;">0</span><span>;
</span><span> </span><span style="color:#407959;">box-sizing</span><span>: </span><span style="color:#b57614;">border-box</span><span>;
</span><span> </span><span style="color:#b57614;">-webkit-</span><span style="color:#407959;">box-sizing</span><span>: </span><span style="color:#b57614;">border-box</span><span>;
</span><span> </span><span style="color:#b57614;">-moz-</span><span style="color:#407959;">box-sizing</span><span>: </span><span style="color:#b57614;">border-box</span><span>;
</span><span> </span><span style="color:#b57614;">-webkit-</span><span style="color:#407959;">font-smoothing</span><span>: </span><span style="color:#b57614;">antialiased</span><span>;
</span><span> </span><span style="color:#b57614;">-moz-</span><span style="color:#407959;">font-smoothing</span><span>: </span><span style="color:#b57614;">antialiased</span><span>;
</span><span> </span><span style="color:#b57614;">-o-</span><span style="color:#407959;">font-smoothing</span><span>: </span><span style="color:#b57614;">antialiased</span><span>;
</span><span> </span><span style="color:#407959;">font-smoothing</span><span>: </span><span style="color:#b57614;">antialiased</span><span>;
</span><span> </span><span style="color:#407959;">text-rendering</span><span>: </span><span style="color:#b57614;">optimizeLegibility</span><span>;
</span><span>}
</span><span>
</span><span style="font-weight:bold;color:#9d0006;">body </span><span>{
</span><span> </span><span style="color:#407959;">font-family</span><span>: </span><span style="color:#79740e;">"Roboto"</span><span>, </span><span style="color:#79740e;">Helvetica</span><span>, </span><span style="color:#79740e;">Arial</span><span>, </span><span style="color:#b57614;">sans-serif</span><span>;
</span><span> </span><span style="color:#407959;">font-weight</span><span>: </span><span style="color:#b57614;">100</span><span>;
</span><span> </span><span style="color:#407959;">font-size</span><span>: </span><span style="color:#b57614;">12</span><span style="color:#8f3f71;">px</span><span>;
</span><span> </span><span style="color:#407959;">line-height</span><span>: </span><span style="color:#b57614;">30</span><span style="color:#8f3f71;">px</span><span>;
</span><span> </span><span style="color:#407959;">color</span><span>: </span><span style="color:#076678;">#777</span><span>;
</span><span> </span><span style="color:#407959;">background</span><span>: </span><span style="color:#076678;">#4CAF50</span><span>;
</span><span>}
</span><span>
</span><span style="color:#79740e;">.container </span><span>{
</span><span> </span><span style="color:#407959;">max-width</span><span>: </span><span style="color:#b57614;">400</span><span style="color:#8f3f71;">px</span><span>;
</span><span> </span><span style="color:#407959;">width</span><span>: </span><span style="color:#b57614;">100</span><span style="color:#8f3f71;">%</span><span>;
</span><span> </span><span style="color:#407959;">margin</span><span>: </span><span style="color:#b57614;">0 auto</span><span>;
</span><span> </span><span style="color:#407959;">position</span><span>: </span><span style="color:#b57614;">relative</span><span>;
</span><span>}
</span><span>
</span><span style="color:#79740e;">#contact </span><span style="font-weight:bold;color:#9d0006;">input</span><span style="color:#79740e;">[</span><span style="color:#407959;">type</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">"text"],
</span><span style="color:#79740e;">#contact </span><span style="font-weight:bold;color:#9d0006;">textarea</span><span style="color:#79740e;">,
</span><span style="color:#79740e;">#contact </span><span style="font-weight:bold;color:#9d0006;">button</span><span style="color:#79740e;">[</span><span style="color:#407959;">type</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">"submit"] </span><span>{
</span><span> </span><span style="color:#407959;">font</span><span>: </span><span style="color:#b57614;">400 12</span><span style="color:#8f3f71;">px</span><span>/</span><span style="color:#b57614;">16</span><span style="color:#8f3f71;">px </span><span style="color:#79740e;">"Roboto"</span><span>, </span><span style="color:#79740e;">Helvetica</span><span>, </span><span style="color:#79740e;">Arial</span><span>, </span><span style="color:#b57614;">sans-serif</span><span>;
</span><span>}
</span><span>
</span><span style="color:#79740e;">#contact </span><span>{
</span><span> </span><span style="color:#407959;">background</span><span>: </span><span style="color:#076678;">#F9F9F9</span><span>;
</span><span> </span><span style="color:#407959;">padding</span><span>: </span><span style="color:#b57614;">25</span><span style="color:#8f3f71;">px</span><span>;
</span><span> </span><span style="color:#407959;">margin</span><span>: </span><span style="color:#b57614;">150</span><span style="color:#8f3f71;">px </span><span style="color:#b57614;">0</span><span>;
</span><span> </span><span style="color:#407959;">box-shadow</span><span>: </span><span style="color:#b57614;">0 0 20</span><span style="color:#8f3f71;">px </span><span style="color:#b57614;">0 rgba</span><span style="color:#282828;">(</span><span style="color:#b57614;">0</span><span style="color:#282828;">, </span><span style="color:#b57614;">0</span><span style="color:#282828;">, </span><span style="color:#b57614;">0</span><span style="color:#282828;">, </span><span style="color:#b57614;">0.2</span><span style="color:#282828;">)</span><span>, </span><span style="color:#b57614;">0 5</span><span style="color:#8f3f71;">px </span><span style="color:#b57614;">5</span><span style="color:#8f3f71;">px </span><span style="color:#b57614;">0 rgba</span><span style="color:#282828;">(</span><span style="color:#b57614;">0</span><span style="color:#282828;">, </span><span style="color:#b57614;">0</span><span style="color:#282828;">, </span><span style="color:#b57614;">0</span><span style="color:#282828;">, </span><span style="color:#b57614;">0.24</span><span style="color:#282828;">)</span><span>;
</span><span>}
</span><span>
</span><span style="color:#79740e;">#contact </span><span style="font-weight:bold;color:#9d0006;">h3 </span><span>{
</span><span> </span><span style="color:#407959;">display</span><span>: </span><span style="color:#b57614;">block</span><span>;
</span><span> </span><span style="color:#407959;">font-size</span><span>: </span><span style="color:#b57614;">30</span><span style="color:#8f3f71;">px</span><span>;
</span><span> </span><span style="color:#407959;">font-weight</span><span>: </span><span style="color:#b57614;">300</span><span>;
</span><span> </span><span style="color:#407959;">margin-bottom</span><span>: </span><span style="color:#b57614;">10</span><span style="color:#8f3f71;">px</span><span>;
</span><span>}
</span><span>
</span><span style="color:#79740e;">#contact </span><span style="font-weight:bold;color:#9d0006;">h4 </span><span>{
</span><span> </span><span style="color:#407959;">margin</span><span>: </span><span style="color:#b57614;">5</span><span style="color:#8f3f71;">px </span><span style="color:#b57614;">0 15</span><span style="color:#8f3f71;">px</span><span>;
</span><span> </span><span style="color:#407959;">display</span><span>: </span><span style="color:#b57614;">block</span><span>;
</span><span> </span><span style="color:#407959;">font-size</span><span>: </span><span style="color:#b57614;">13</span><span style="color:#8f3f71;">px</span><span>;
</span><span> </span><span style="color:#407959;">font-weight</span><span>: </span><span style="color:#b57614;">400</span><span>;
</span><span>}
</span><span>
</span><span style="font-weight:bold;color:#9d0006;">fieldset </span><span>{
</span><span> </span><span style="color:#407959;">border</span><span>: </span><span style="color:#b57614;">medium none </span><span style="color:#9d0006;">!important</span><span>;
</span><span> </span><span style="color:#407959;">margin</span><span>: </span><span style="color:#b57614;">0 0 10</span><span style="color:#8f3f71;">px</span><span>;
</span><span> </span><span style="color:#407959;">min-width</span><span>: </span><span style="color:#b57614;">100</span><span style="color:#8f3f71;">%</span><span>;
</span><span> </span><span style="color:#407959;">padding</span><span>: </span><span style="color:#b57614;">0</span><span>;
</span><span> </span><span style="color:#407959;">width</span><span>: </span><span style="color:#b57614;">100</span><span style="color:#8f3f71;">%</span><span>;
</span><span>}
</span><span>
</span><span style="color:#79740e;">#contact </span><span style="font-weight:bold;color:#9d0006;">input</span><span style="color:#79740e;">[</span><span style="color:#407959;">type</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">"text"],
</span><span style="color:#79740e;">#contact </span><span style="font-weight:bold;color:#9d0006;">textarea </span><span>{
</span><span> </span><span style="color:#407959;">width</span><span>: </span><span style="color:#b57614;">100</span><span style="color:#8f3f71;">%</span><span>;
</span><span> </span><span style="color:#407959;">border</span><span>: </span><span style="color:#b57614;">1</span><span style="color:#8f3f71;">px </span><span style="color:#b57614;">solid </span><span style="color:#076678;">#ccc</span><span>;
</span><span> </span><span style="color:#407959;">background</span><span>: </span><span style="color:#076678;">#FFF</span><span>;
</span><span> </span><span style="color:#407959;">margin</span><span>: </span><span style="color:#b57614;">0 0 5</span><span style="color:#8f3f71;">px</span><span>;
</span><span> </span><span style="color:#407959;">padding</span><span>: </span><span style="color:#b57614;">10</span><span style="color:#8f3f71;">px</span><span>;
</span><span>}
</span><span>
</span><span style="color:#79740e;">#contact </span><span style="font-weight:bold;color:#9d0006;">input</span><span style="color:#79740e;">[</span><span style="color:#407959;">type</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">"text"]:</span><span style="color:#407959;">hover</span><span style="color:#79740e;">,
</span><span style="color:#79740e;">#contact </span><span style="font-weight:bold;color:#9d0006;">textarea</span><span style="color:#79740e;">:</span><span style="color:#407959;">hover </span><span>{
</span><span> </span><span style="color:#b57614;">-webkit-</span><span style="color:#407959;">transition</span><span>: </span><span style="color:#b57614;">border-color 0.3</span><span style="color:#8f3f71;">s </span><span style="color:#b57614;">ease-in-out</span><span>;
</span><span> </span><span style="color:#b57614;">-moz-</span><span style="color:#407959;">transition</span><span>: </span><span style="color:#b57614;">border-color 0.3</span><span style="color:#8f3f71;">s </span><span style="color:#b57614;">ease-in-out</span><span>;
</span><span> </span><span style="color:#407959;">transition</span><span>: </span><span style="color:#b57614;">border-color 0.3</span><span style="color:#8f3f71;">s </span><span style="color:#b57614;">ease-in-out</span><span>;
</span><span> </span><span style="color:#407959;">border</span><span>: </span><span style="color:#b57614;">1</span><span style="color:#8f3f71;">px </span><span style="color:#b57614;">solid </span><span style="color:#076678;">#aaa</span><span>;
</span><span>}
</span><span>
</span><span style="color:#79740e;">#contact </span><span style="font-weight:bold;color:#9d0006;">textarea </span><span>{
</span><span> </span><span style="color:#407959;">height</span><span>: </span><span style="color:#b57614;">100</span><span style="color:#8f3f71;">px</span><span>;
</span><span> </span><span style="color:#407959;">max-width</span><span>: </span><span style="color:#b57614;">100</span><span style="color:#8f3f71;">%</span><span>;
</span><span> </span><span style="color:#407959;">resize</span><span>: </span><span style="color:#b57614;">none</span><span>;
</span><span>}
</span><span>
</span><span style="color:#79740e;">#contact </span><span style="font-weight:bold;color:#9d0006;">button</span><span style="color:#79740e;">[</span><span style="color:#407959;">type</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">"submit"] </span><span>{
</span><span> </span><span style="color:#407959;">cursor</span><span>: </span><span style="color:#b57614;">pointer</span><span>;
</span><span> </span><span style="color:#407959;">width</span><span>: </span><span style="color:#b57614;">100</span><span style="color:#8f3f71;">%</span><span>;
</span><span> </span><span style="color:#407959;">border</span><span>: </span><span style="color:#b57614;">none</span><span>;
</span><span> </span><span style="color:#407959;">background</span><span>: </span><span style="color:#076678;">#4CAF50</span><span>;
</span><span> </span><span style="color:#407959;">color</span><span>: </span><span style="color:#076678;">#FFF</span><span>;
</span><span> </span><span style="color:#407959;">margin</span><span>: </span><span style="color:#b57614;">0 0 5</span><span style="color:#8f3f71;">px</span><span>;
</span><span> </span><span style="color:#407959;">padding</span><span>: </span><span style="color:#b57614;">10</span><span style="color:#8f3f71;">px</span><span>;
</span><span> </span><span style="color:#407959;">font-size</span><span>: </span><span style="color:#b57614;">15</span><span style="color:#8f3f71;">px</span><span>;
</span><span>}
</span><span>
</span><span style="color:#79740e;">#contact </span><span style="font-weight:bold;color:#9d0006;">button</span><span style="color:#79740e;">[</span><span style="color:#407959;">type</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">"submit"]:</span><span style="color:#407959;">hover </span><span>{
</span><span> </span><span style="color:#407959;">background</span><span>: </span><span style="color:#076678;">#43A047</span><span>;
</span><span> </span><span style="color:#b57614;">-webkit-</span><span style="color:#407959;">transition</span><span>: </span><span style="color:#b57614;">background 0.3</span><span style="color:#8f3f71;">s </span><span style="color:#b57614;">ease-in-out</span><span>;
</span><span> </span><span style="color:#b57614;">-moz-</span><span style="color:#407959;">transition</span><span>: </span><span style="color:#b57614;">background 0.3</span><span style="color:#8f3f71;">s </span><span style="color:#b57614;">ease-in-out</span><span>;
</span><span> </span><span style="color:#407959;">transition</span><span>: </span><span style="color:#b57614;">background-color 0.3</span><span style="color:#8f3f71;">s </span><span style="color:#b57614;">ease-in-out</span><span>;
</span><span>}
</span><span>
</span><span style="color:#79740e;">#contact </span><span style="font-weight:bold;color:#9d0006;">button</span><span style="color:#79740e;">[</span><span style="color:#407959;">type</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">"submit"]:</span><span style="color:#407959;">active </span><span>{
</span><span> </span><span style="color:#407959;">box-shadow</span><span>: </span><span style="color:#b57614;">inset 0 1</span><span style="color:#8f3f71;">px </span><span style="color:#b57614;">3</span><span style="color:#8f3f71;">px </span><span style="color:#b57614;">rgba</span><span style="color:#282828;">(</span><span style="color:#b57614;">0</span><span style="color:#282828;">, </span><span style="color:#b57614;">0</span><span style="color:#282828;">, </span><span style="color:#b57614;">0</span><span style="color:#282828;">, </span><span style="color:#b57614;">0.5</span><span style="color:#282828;">)</span><span>;
</span><span>}
</span><span>
</span><span style="color:#79740e;">.copyright </span><span>{
</span><span> </span><span style="color:#407959;">text-align</span><span>: </span><span style="color:#b57614;">center</span><span>;
</span><span>}
</span><span>
</span><span style="color:#79740e;">#contact </span><span style="font-weight:bold;color:#9d0006;">input</span><span style="color:#79740e;">:</span><span style="color:#407959;">focus</span><span style="color:#79740e;">,
</span><span style="color:#79740e;">#contact </span><span style="font-weight:bold;color:#9d0006;">textarea</span><span style="color:#79740e;">:</span><span style="color:#407959;">focus </span><span>{
</span><span> </span><span style="color:#407959;">outline</span><span>: </span><span style="color:#b57614;">0</span><span>;
</span><span> </span><span style="color:#407959;">border</span><span>: </span><span style="color:#b57614;">1</span><span style="color:#8f3f71;">px </span><span style="color:#b57614;">solid </span><span style="color:#076678;">#aaa</span><span>;
</span><span>}
</span><span>
</span><span style="color:#79740e;">::</span><span style="color:#b57614;">-webkit-</span><span style="color:#407959;">input-placeholder </span><span>{
</span><span> </span><span style="color:#407959;">color</span><span>: </span><span style="color:#076678;">#888</span><span>;
</span><span>}
</span><span>
</span><span style="color:#79740e;">:</span><span style="color:#407959;">-moz-placeholder </span><span>{
</span><span> </span><span style="color:#407959;">color</span><span>: </span><span style="color:#076678;">#888</span><span>;
</span><span>}
</span><span>
</span><span style="color:#79740e;">::</span><span style="color:#b57614;">-moz-</span><span style="color:#407959;">placeholder </span><span>{
</span><span> </span><span style="color:#407959;">color</span><span>: </span><span style="color:#076678;">#888</span><span>;
</span><span>}
</span><span>
</span><span style="color:#79740e;">:</span><span style="color:#407959;">-ms-input-placeholder </span><span>{
</span><span> </span><span style="color:#407959;">color</span><span>: </span><span style="color:#076678;">#888</span><span>;
</span><span>}
</span></code></pre>
<p>Tinggal include html css tadi ke jekyll. Hasilnya setelah dijadikan satu dengan jekyll dapat dilihat di <a href="https://kritik.sumarsono.com">sini</a></p>
<script async src="https://telegram.org/js/telegram-widget.js?5" data-telegram-post="unomindgithubio/29" data-width="100%"></script>
<p>Misalnya kita isi formnya dan submit, hasilnya akan terkirim ke google form yg tadi dibuat:</p>
<script async src="https://telegram.org/js/telegram-widget.js?5" data-telegram-post="unomindgithubio/30" data-width="100%"></script>
Cara Mudah Install I3 WM Siap Pakai di Manjaro
2019-04-07T14:25:34+07:00
2019-04-07T14:25:34+07:00
Unknown
https://www.sumarsono.com/cara-mudah-install-i3-wm-siap-pakai-di-manjaro/
<p>Pakai distro Manjaro? Bosan dengan DE? ingin coba WM? tapi males konfig sana sini? Nah, ini solusinya. Install I3 WM tanpa ribet, modal klik selesai siap pakai. Hahaha.</p>
<p>Pertama, buka software center, kebetulan saya pakai pamac. Kemudian centang paket seperti skrinsut dibawah, dan apply:</p>
<script async src="https://telegram.org/js/telegram-widget.js?5" data-telegram-post="unomindgithubio/22" data-width="100%" data-single></script>
<p>Kedua, bikin user baru, saya bikin lewat user manager KDE karena sedang pakai KDE</p>
<p>Ketiga, logout kemudian pilih User baru tsb, dan pilih sesi i3.</p>
<p>Jreng-jreng, dapet i3 yg cakep sudah siap pakai.</p>
<script async src="https://telegram.org/js/telegram-widget.js?5" data-telegram-post="unomindgithubio/21" data-width="100%"></script>
Replace String dalam Mongodb Field
2019-03-13T15:17:54+07:00
2019-03-13T15:17:54+07:00
Unknown
https://www.sumarsono.com/replace-string-dalam-mongodb-field/
<p>Berususan dengan banyak data memang merepotkan. Tapi ya gimana lagi, haha.</p>
<h1 id="kasus">Kasus</h1>
<p>Saya ada 500000 document dalam sebuah collection mongodb. Data tersebut memiliki format:</p>
<pre data-lang="json" style="background-color:#fcf0ca;color:#282828aa;" class="language-json "><code class="language-json" data-lang="json"><span>{
</span><span> </span><span style="color:#79740e;">"_id" </span><span>: </span><span style="background-color:#932b1e;color:#282828;">ObjectId(</span><span style="color:#79740e;">"5c81cb961555687199b64caa"</span><span style="background-color:#932b1e;color:#282828;">),</span><span>
</span><span> </span><span style="color:#79740e;">"name" </span><span>: </span><span style="color:#79740e;">"Sumarsono"</span><span>,
</span><span> </span><span style="color:#79740e;">"no" </span><span>: </span><span style="color:#79740e;">"001-963258741"</span><span>,
</span><span> </span><span style="color:#79740e;">"create_date" </span><span>: </span><span style="background-color:#932b1e;color:#282828;">ISODate(</span><span style="color:#79740e;">"2019-03-08T08:55:34.605Z"</span><span style="background-color:#932b1e;color:#282828;">),</span><span>
</span><span> </span><span style="color:#79740e;">"update_date" </span><span>: </span><span style="background-color:#932b1e;color:#282828;">ISODate(</span><span style="color:#79740e;">"2019-03-08T08:55:34.605Z"</span><span style="background-color:#932b1e;color:#282828;">)</span><span>
</span><span>}
</span></code></pre>
<p>Dari data tersebut, saya ingin membuang <code>001-</code> dari field <code>no</code> dan menyisakan angka setelah <code>001-</code>. Edit satu-satu? jangan bercanda, ada 500ribu data.
Cara tercepat adalah dengan memanfaatkan fungsi yang ada di mongo shell. Hasil akhir yang ingin dicapai adalah:</p>
<pre data-lang="json" style="background-color:#fcf0ca;color:#282828aa;" class="language-json "><code class="language-json" data-lang="json"><span>{
</span><span> </span><span style="color:#79740e;">"_id" </span><span>: </span><span style="background-color:#932b1e;color:#282828;">ObjectId(</span><span style="color:#79740e;">"5c81cb961555687199b64caa"</span><span style="background-color:#932b1e;color:#282828;">),</span><span>
</span><span> </span><span style="color:#79740e;">"name" </span><span>: </span><span style="color:#79740e;">"Sumarsono"</span><span>,
</span><span> </span><span style="color:#79740e;">"no" </span><span>: </span><span style="color:#79740e;">"963258741"</span><span>,
</span><span> </span><span style="color:#79740e;">"create_date" </span><span>: </span><span style="background-color:#932b1e;color:#282828;">ISODate(</span><span style="color:#79740e;">"2019-03-08T08:55:34.605Z"</span><span style="background-color:#932b1e;color:#282828;">),</span><span>
</span><span> </span><span style="color:#79740e;">"update_date" </span><span>: </span><span style="background-color:#932b1e;color:#282828;">ISODate(</span><span style="color:#79740e;">"2019-03-08T08:55:34.605Z"</span><span style="background-color:#932b1e;color:#282828;">)</span><span>
</span><span>}
</span></code></pre>
<p>Struktur database:</p>
<ul>
<li>nama db : mydb</li>
<li>nama collection: my_collection</li>
</ul>
<h1 id="solusi">Solusi</h1>
<p>masuk ke mongo shell dengan command <code>mongo</code>, kemudian eksekusi command berikut:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#b23c15;">></span><span> use </span><span style="color:#282828;">mydb
</span><span style="color:#b23c15;">></span><span> db.getCollection(</span><span style="color:#79740e;">'my_collection'</span><span>)</span><span style="color:#282828;">.find(</span><span>)</span><span style="color:#282828;">.forEach(function(doc</span><span>) {
</span><span> </span><span style="color:#282828;">doc.no = doc.no.replace(</span><span style="color:#79740e;">'001-'</span><span style="color:#282828;">, </span><span style="color:#79740e;">''</span><span>)</span><span style="color:#b23c15;">;
</span><span> </span><span style="color:#282828;">db.getCollection(</span><span style="color:#79740e;">'my_collection'</span><span>)</span><span style="color:#282828;">.save(doc</span><span>)</span><span style="color:#b23c15;">;
</span><span>})</span><span style="color:#b23c15;">;
</span></code></pre>
<p>Atau lewat Aplikasi Robo3T, cukup dobel klik <code>my_collection</code>, kemudian pada bar command paste:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>db.getCollection('my_collection').find().forEach(function(doc) {
</span><span> doc.no = doc.no.replace('001-', '');
</span><span> db.getCollection('my_collection').save(doc);
</span><span>});
</span></code></pre>
<p>Kemudian tekan CTRL+ENTER</p>
<p>Cara ini cukup cepat, dari pengalamanku untuk 500 ribu data, tidak ada 3 menit.</p>
<blockquote>
<p>Note: Jangan lupa selalu backup sebelum eksekusi sesuatu</p>
</blockquote>
Install Webmin di Raspberry Pi 3
2019-03-13T09:27:05+07:00
2019-03-13T09:27:05+07:00
Unknown
https://www.sumarsono.com/install-webmin-di-raspberry-pi-3/
<h1 id="intro">Intro</h1>
<p>Webmin is a web-based interface for system administration for Unix. Using any browser that supports tables and forms (and Java for the File Manager module), you can setup user accounts, Apache, DNS, file sharing and so on.</p>
<p>Webmin consists of a simple web server, and a number of CGI programs which directly update system files like /etc/inetd.conf and /etc/passwd. The web server and all CGI programs are written in Perl version 5, and use no non-standard Perl modules. </p>
<p>-- <a href="http://www.webmin.com/intro.html">dimari</a></p>
<h1 id="host">Host</h1>
<ul>
<li>Device: Raspberry Pi 3</li>
<li>OS: Raspbian Stretch Lite</li>
</ul>
<h1 id="proses-install">Proses Install</h1>
<ul>
<li>Install deps</li>
</ul>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo apt install perl libnet-ssleay-perl openssl libauthen-pam-perl libpam-runtime libio-pty-perl apt-show-versions python
</span></code></pre>
<ul>
<li>Download installer Webmin</li>
</ul>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>wget http://prdownloads.sourceforge.net/webadmin/webmin_1.900_all.deb
</span></code></pre>
<ul>
<li>Install Webmin</li>
</ul>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo dpkg --install webmin_1.900_all.deb
</span></code></pre>
<ul>
<li>Disable SSL (kalau tidak, laman webmin tidak akan terbuka)</li>
</ul>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>nano /etc/webmin/miniserv.conf
</span><span>Cari baris:
</span><span>ssl=1
</span><span>Kemudian ganti dengan:
</span><span>ssl=0
</span></code></pre>
<ul>
<li>Restart webmin</li>
</ul>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo systemctl restart webmin
</span></code></pre>
<p>Selesai</p>
Portainer: Sebuah GUI untuk docker
2019-03-08T08:07:36+07:00
2019-03-08T08:07:36+07:00
Unknown
https://www.sumarsono.com/portainer-sebuah-gui-untuk-docker/
<script async src="https://telegram.org/js/telegram-widget.js?5" data-telegram-post="unomindgithubio/15" data-width="100%"></script>
<p>Saya masih lanjut belajar docker, ketersediaan image siap pakai benar-benar membantu. Saya jadi tidak perlu repot dengan dependensi sebuah paket, systemku jadi "clean" ketika jadi sawah dengan banyak anuan.</p>
<p>Manajemen docker dari CLI sudah lebih dari cukup, sebenarnya. Namun demikian, rasanya kurang nganu kalau selalu lewat CLI. Maka dari itu saya mencari-cari frontend GUI untuk manajemen docker, kalau ada yg web based. Akhir dari pencarian itu, saya menambatkan hati pada <a href="https://portainer.io">Portainer</a>.</p>
<p>Installnya cukup mudah, ada dua pilihan lewat docker container atau ambil versi non docker. Kalian bisa membacanya di <a href="https://portainer.readthedocs.io/en/latest/deployment.html">dokumentasi mereka</a>. Disini saya kutip saja:</p>
<h1 id="portainer-versi-docker">Portainer versi docker</h1>
<p>Pertama create docker volume untuk portainer:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo docker volume create portainer_data
</span><span>
</span></code></pre>
<p>Kedua run portainer</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo docker run --name portainer --restart always -d -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer
</span></code></pre>
<p>Selanjutnya silakan buka di browser port 9000.</p>
<h1 id="portainer-non-docker">Portainer non docker</h1>
<p>Download dan ekstrak:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>cd /opt
</span><span>wget https://github.com/portainer/portainer/releases/download/1.20.1/portainer-1.20.1-linux-amd64.tar.gz
</span><span>tar xvpfz portainer-1.20.1-linux-amd64.tar.gz
</span></code></pre>
<p>Create folder data dan Start portainer:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>mkdir /opt/portainer-data
</span><span>cd /opt/portainer
</span><span>./portainer --data /opt/portainer-data --template-file "${PWD}/templates.json"
</span></code></pre>
<p>Selanjutnya silakan buka di browser port 9000.</p>
Sublimetext: Replace Char dengan Newline
2019-03-06T14:56:03+07:00
2019-03-06T14:56:03+07:00
Unknown
https://www.sumarsono.com/sublimetext-replace-char-dengan-newline/
<p>Replace char dalam ribuan data memang merepotkan. Kita butuh bantuan tool.</p>
<p>Contoh kasus:</p>
<p>Saya ada data seperti berikut:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>'('nama','anuan')','('nama','ituan')','('nama','anuku')','('nama','ituku')', ... .'('nama','blabla')'
</span></code></pre>
<p>Data tersebut ada 1 juta pasang key dan value. Saya ingin replace <code>)','(</code> dengan newline, sehingga menjadi:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>'('nama','anuan'
</span><span>'nama','ituan'
</span><span>'nama','anuku'
</span><span>'nama','ituku'
</span><span> ...
</span><span>'nama','blabla')'
</span></code></pre>
<p>Apa yang saya lakukan? Supaya tidak masokis, saya pakai sublimetext.</p>
<ul>
<li>Buka data tsb di sublimetext</li>
<li>Gunakan fitur search and replace (CTRL+H)</li>
<li>Pada kolom search isi dengan <code>)','(</code></li>
<li>Pada kolom replace, tekan CTRL+enter</li>
<li>Klik Replace All</li>
</ul>
<p>Done</p>
Directory List yang Cantik dan Praktis a la Caddy
2019-02-20T10:03:26+07:00
2019-02-20T10:03:26+07:00
Unknown
https://www.sumarsono.com/directory-list-yang-cantik-dan-praktis-a-la-caddy/
<p>Ingin share lewat web? Mudah kok. Tinggal pakai direktory listing. Apache httpd, ada +Indexes. Nginx, ada autoindex. Caddy,
ada browse. Kebetulan saat
ini mau coba caddy. Tampilannya seperti gambar diatas.</p>
<p>Caddyfile:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sub.domain.tld {
</span><span> root /var/www/html/files
</span><span> browse /
</span><span>}
</span></code></pre>
<p>Gitu doang konfignya, hahaha.</p>
Pindah dari adaline:dockermail-core ke tvial:docker-mailserver
2019-02-15T19:46:41+07:00
2019-02-15T19:46:41+07:00
Unknown
https://www.sumarsono.com/pindah-dari-adaline-dockermail-core-ke-tvial-docker-mailserver/
<p>Kenapa pindah? karena adaline sudah lama gk maintain, sepi juga develnya. Kemudian yang paling berasa krusial banget, gk ada dukungan SSL, kalau mau nambah sendiri ribet. Gk ada faedahnya saya pakai docker. Untungnya ada mailserver versi docker yang akif banget, milik tvial. Develnya ramai, dukungan SSL, spam assassin, clamav, etc. Langsung ke docker hubnya saja kalau penasaran. Hahaha. Setupnya juga mudah, ada disana.</p>
<p>Snipset docker-compose.yml yang saya pakai:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>version: '2'
</span><span>services:
</span><span> mail:
</span><span> image: tvial/docker-mailserver:latest
</span><span> hostname: ${HOSTNAME}
</span><span> domainname: ${DOMAINNAME}
</span><span> container_name: ${CONTAINER_NAME}
</span><span> ports:
</span><span> - "25:25"
</span><span> - "143:143"
</span><span> - "465:465"
</span><span> - "587:587"
</span><span> - "993:993"
</span><span> volumes:
</span><span> - maildata:/var/mail
</span><span> - mailstate:/var/mail-state
</span><span> - ./config/:/tmp/docker-mailserver/
</span><span> - ./letsencrypt/:/etc/letsencrypt/
</span><span> environment:
</span><span> - DMS_DEBUG=${DMS_DEBUG}
</span><span> - ENABLE_CLAMAV=${ENABLE_CLAMAV}
</span><span> - ONE_DIR=${ONE_DIR}
</span><span> - ENABLE_POP3=${ENABLE_POP3}
</span><span> - ENABLE_FAIL2BAN=${ENABLE_FAIL2BAN}
</span><span> - ENABLE_MANAGESIEVE=${ENABLE_MANAGESIEVE}
</span><span> - OVERRIDE_HOSTNAME=${OVERRIDE_HOSTNAME}
</span><span> - POSTMASTER_ADDRESS=${POSTMASTER_ADDRESS}
</span><span> - POSTSCREEN_ACTION=${POSTSCREEN_ACTION}
</span><span> - REPORT_RECIPIENT=${REPORT_RECIPIENT}
</span><span> - REPORT_SENDER=${REPORT_SENDER}
</span><span> - REPORT_INTERVAL=${REPORT_INTERVAL}
</span><span> - SMTP_ONLY=${SMTP_ONLY}
</span><span> - SSL_TYPE=${SSL_TYPE}
</span><span> - TLS_LEVEL=${TLS_LEVEL}
</span><span> - SPOOF_PROTECTION=${SPOOF_PROTECTION}
</span><span> - ENABLE_SRS=${ENABLE_SRS}
</span><span> - PERMIT_DOCKER=${PERMIT_DOCKER}
</span><span> - VIRUSMAILS_DELETE_DELAY=${VIRUSMAILS_DELETE_DELAY}
</span><span> - ENABLE_POSTFIX_VIRTUAL_TRANSPORT=${ENABLE_POSTFIX_VIRTUAL_TRANSPORT}
</span><span> - POSTFIX_DAGENT=${POSTFIX_DAGENT}
</span><span> - POSTFIX_MAILBOX_SIZE_LIMIT=${POSTFIX_MAILBOX_SIZE_LIMIT}
</span><span> - POSTFIX_MESSAGE_SIZE_LIMIT=${POSTFIX_MESSAGE_SIZE_LIMIT}
</span><span> - ENABLE_SPAMASSASSIN=${ENABLE_SPAMASSASSIN}
</span><span> - SA_TAG=${SA_TAG}
</span><span> - SA_TAG2=${SA_TAG2}
</span><span> - SA_KILL=${SA_KILL}
</span><span> - SA_SPAM_SUBJECT=${SA_SPAM_SUBJECT}
</span><span> - ENABLE_FETCHMAIL=${ENABLE_FETCHMAIL}
</span><span> - FETCHMAIL_POLL=${FETCHMAIL_POLL}
</span><span> - ENABLE_LDAP=${ENABLE_LDAP}
</span><span> - LDAP_START_TLS=${LDAP_START_TLS}
</span><span> - LDAP_SERVER_HOST=${LDAP_SERVER_HOST}
</span><span> - LDAP_SEARCH_BASE=${LDAP_SEARCH_BASE}
</span><span> - LDAP_BIND_DN=${LDAP_BIND_DN}
</span><span> - LDAP_BIND_PW=${LDAP_BIND_PW}
</span><span> - LDAP_QUERY_FILTER_USER=${LDAP_QUERY_FILTER_USER}
</span><span> - LDAP_QUERY_FILTER_GROUP=${LDAP_QUERY_FILTER_GROUP}
</span><span> - LDAP_QUERY_FILTER_ALIAS=${LDAP_QUERY_FILTER_ALIAS}
</span><span> - LDAP_QUERY_FILTER_DOMAIN=${LDAP_QUERY_FILTER_DOMAIN}
</span><span> - DOVECOT_TLS=${DOVECOT_TLS}
</span><span> - DOVECOT_USER_FILTER=${DOVECOT_USER_FILTER}
</span><span> - DOVECOT_PASS_FILTER=${DOVECOT_PASS_FILTER}
</span><span> - ENABLE_POSTGREY=${ENABLE_POSTGREY}
</span><span> - POSTGREY_DELAY=${POSTGREY_DELAY}
</span><span> - POSTGREY_MAX_AGE=${POSTGREY_MAX_AGE}
</span><span> - POSTGREY_AUTO_WHITELIST_CLIENTS=${POSTGREY_AUTO_WHITELIST_CLIENTS}
</span><span> - POSTGREY_TEXT=${POSTGREY_TEXT}
</span><span> - ENABLE_SASLAUTHD=${ENABLE_SASLAUTHD}
</span><span> - SASLAUTHD_MECHANISMS=${SASLAUTHD_MECHANISMS}
</span><span> - SASLAUTHD_MECH_OPTIONS=${SASLAUTHD_MECH_OPTIONS}
</span><span> - SASLAUTHD_LDAP_SERVER=${SASLAUTHD_LDAP_SERVER}
</span><span> - SASLAUTHD_LDAP_SSL=${SASLAUTHD_LDAP_SSL}
</span><span> - SASLAUTHD_LDAP_BIND_DN=${SASLAUTHD_LDAP_BIND_DN}
</span><span> - SASLAUTHD_LDAP_PASSWORD=${SASLAUTHD_LDAP_PASSWORD}
</span><span> - SASLAUTHD_LDAP_SEARCH_BASE=${SASLAUTHD_LDAP_SEARCH_BASE}
</span><span> - SASLAUTHD_LDAP_FILTER=${SASLAUTHD_LDAP_FILTER}
</span><span> - SASLAUTHD_LDAP_START_TLS=${SASLAUTHD_LDAP_START_TLS}
</span><span> - SASLAUTHD_LDAP_TLS_CHECK_PEER=${SASLAUTHD_LDAP_TLS_CHECK_PEER}
</span><span> - SASL_PASSWD=${SASL_PASSWD}
</span><span> - SRS_EXCLUDE_DOMAINS=${SRS_EXCLUDE_DOMAINS}
</span><span> - SRS_SECRET=${SRS_SECRET}
</span><span> - DEFAULT_RELAY_HOST=${DEFAULT_RELAY_HOST}
</span><span> - RELAY_HOST=${RELAY_HOST}
</span><span> - RELAY_PORT=${RELAY_PORT}
</span><span> - RELAY_USER=${RELAY_USER}
</span><span> - RELAY_PASSWORD=${RELAY_PASSWORD}
</span><span> cap_add:
</span><span> - NET_ADMIN
</span><span> - SYS_PTRACE
</span><span> restart: always
</span><span>volumes:
</span><span> maildata:
</span><span> driver: local
</span><span> mailstate:
</span><span> driver: local
</span></code></pre>
<p>Bagian <code>- ./letsencrypt/:/etc/letsencrypt/</code>, isi dari ./letsencrypt saya copas dari /etc/letsencrypt.</p>
<p>Snipset .env:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span># -----------------------------------------------------------------------------------------------------------------------------
</span><span># --------------------- General Settings --------------------------------------------------------------------------------------
</span><span># -----------------------------------------------------------------------------------------------------------------------------
</span><span>
</span><span>HOSTNAME=vps
</span><span>DOMAINNAME=sumarsono.com
</span><span>CONTAINER_NAME=mailserver
</span><span>
</span><span># empty => uses the `hostname` command to get the mail server's canonical hostname
</span><span># => Specify a fully-qualified domainname to serve mail for. This is used for many of the config features so if you can't set your hostname (e.g. you're in a container platform that doesn't let you) specify it in this environment variable.
</span><span>OVERRIDE_HOSTNAME=vps.sumarsono.com
</span><span>
</span><span># 0 => Debug disabled
</span><span># 1 => Enables debug on startup
</span><span>DMS_DEBUG=0
</span><span>
</span><span># 0 => mail state in default directories
</span><span># 1 => consolidate all states into a single directory (`/var/mail-state`) to allow persistence using docker volumes
</span><span>ONE_DIR=0
</span><span>
</span><span># empty => postmaster@domain.com
</span><span># => Specify the postmaster address
</span><span>POSTMASTER_ADDRESS=postmaster@sumarsono.com
</span><span>
</span><span># Set different options for mynetworks option (can be overwrite in postfix-main.cf)
</span><span># empty => localhost only
</span><span># host => Add docker host (ipv4 only)
</span><span># network => Add all docker containers (ipv4 only)
</span><span>PERMIT_DOCKER=
</span><span>
</span><span># empty => modern
</span><span># modern => Enables TLSv1.2 and modern ciphers only. (default)
</span><span># intermediate => Enables TLSv1, TLSv1.1 and TLSv1.2 and broad compatibility ciphers.
</span><span># old => NOT implemented. If you really need it, then customize the TLS ciphers overriding postfix and dovecot settings
</span><span># (https://github.com/tomav/docker-mailserver/wiki/)
</span><span>TLS_LEVEL=
</span><span>
</span><span># Configures the handling of creating mails with forged sender addresses.
</span><span>#
</span><span># empty => (not recommended, but default for backwards compatability reasons)
</span><span># Mail address spoofing allowed. Any logged in user may create email messages with a forged sender address.
</span><span># See also https://en.wikipedia.org/wiki/Email_spoofing
</span><span># 1 => (recommended) Mail spoofing denied. Each user may only send with his own or his alias addresses.
</span><span># Addresses with extension delimiters(http://www.postfix.org/postconf.5.html#recipient_delimiter) are not able to send messages.
</span><span>SPOOF_PROTECTION=1
</span><span>
</span><span># Enables the Sender Rewriting Scheme. SRS is needed if your mail server acts as forwarder. See [postsrsd](https://github.com/roehling/postsrsd/blob/master/README.md#sender-rewriting-scheme-crash-course) for further explanation.
</span><span># - **0** => Disabled
</span><span># - 1 => Enabled
</span><span>ENABLE_SRS=0
</span><span>
</span><span># 1 => Enables POP3 service
</span><span># empty => disables POP3
</span><span>ENABLE_POP3=
</span><span>ENABLE_CLAMAV=0
</span><span>
</span><span># If you enable Fail2Ban, don't forget to add the following lines to your `docker-compose.yml`:
</span><span># cap_add:
</span><span># - NET_ADMIN
</span><span># Otherwise, `iptables` won't be able to ban IPs.
</span><span>ENABLE_FAIL2BAN=0
</span><span>
</span><span># 1 => Enables Managesieve on port 4190
</span><span># empty => disables Managesieve
</span><span>ENABLE_MANAGESIEVE=
</span><span>
</span><span># **enforce** => Allow other tests to complete. Reject attempts to deliver mail with a 550 SMTP reply, and log the helo/sender/recipient information. Repeat this test the next time the client connects.
</span><span># drop => Drop the connection immediately with a 521 SMTP reply. Repeat this test the next time the client connects.
</span><span># ignore => Ignore the failure of this test. Allow other tests to complete. Repeat this test the next time the client connects. This option is useful for testing and collecting statistics without blocking mail.
</span><span>POSTSCREEN_ACTION=enforce
</span><span>
</span><span># empty => all daemons start
</span><span># 1 => only launch postfix smtp
</span><span>SMTP_ONLY=
</span><span>
</span><span># Please read [the SSL page in the wiki](https://github.com/tomav/docker-mailserver/wiki/Configure-SSL) for more information.
</span><span>#
</span><span># empty => SSL disabled
</span><span># letsencrypt => Enables Let's Encrypt certificates
</span><span># custom => Enables custom certificates
</span><span># manual => Let's you manually specify locations of your SSL certificates for non-standard cases
</span><span># self-signed => Enables self-signed certificates
</span><span>SSL_TYPE=letsencrypt
</span><span>
</span><span># Set how many days a virusmail will stay on the server before being deleted
</span><span># empty => 7 days
</span><span>VIRUSMAILS_DELETE_DELAY=2
</span><span>
</span><span># This Option is activating the Usage of POSTFIX_DAGENT to specify a lmtp client different from default dovecot socket.
</span><span># empty => disabled
</span><span># 1 => enabled
</span><span>ENABLE_POSTFIX_VIRTUAL_TRANSPORT=
</span><span>
</span><span># Enabled by ENABLE_POSTFIX_VIRTUAL_TRANSPORT. Specify the final delivery of postfix
</span><span>#
</span><span># empty => fail
</span><span># `lmtp:unix:private/dovecot-lmtp` (use socket)
</span><span># `lmtps:inet:<host>:<port>` (secure lmtp with starttls, take a look at https://sys4.de/en/blog/2014/11/17/sicheres-lmtp-mit-starttls-in-dovecot/)
</span><span># `lmtp:<kopano-host>:2003` (use kopano as mailstore)
</span><span># etc.
</span><span>POSTFIX_DAGENT=
</span><span>
</span><span># Set the mailbox size limit for all users. If set to zero, the size will be unlimited (default).
</span><span>#
</span><span># empty => 0
</span><span>POSTFIX_MAILBOX_SIZE_LIMIT=
</span><span>
</span><span># Set the message size limit for all users. If set to zero, the size will be unlimited (not recommended!)
</span><span>#
</span><span># empty => 10240000 (~10 MB)
</span><span>POSTFIX_MESSAGE_SIZE_LIMIT=
</span><span>
</span><span># Enables a report being sent (created by pflogsumm) on a regular basis.
</span><span># **0** => Report emails are disabled
</span><span># 1 => Using POSTMASTER_ADDRESS as the recipient
</span><span># => Specify the recipient address
</span><span>REPORT_RECIPIENT=1
</span><span>
</span><span>
</span><span># Change the sending address for mail report
</span><span># **empty** => mailserver-report@hostname
</span><span># => Specify the report sender (From) address
</span><span>REPORT_SENDER=
</span><span>
</span><span># Changes the interval in which a report is being sent.
</span><span># **daily** => Send a daily report
</span><span># weekly => Send a report every week
</span><span># monthly => Send a report every month
</span><span>#
</span><span># Note: This Variable actually controls logrotate inside the container and rotates the log depending on this setting. The main log output is still available in its entirety via `docker logs mail` (Or your respective container name). If you want to control logrotation for the docker generated logfile see: [Docker Logging Drivers](https://docs.docker.com/config/containers/logging/configure/)
</span><span>REPORT_INTERVAL=daily
</span><span>
</span><span># -----------------------------------------------------------------------------------------------------------------------------
</span><span># --------------------- Spamassassin section ----------------------------------------------------------------------------------
</span><span># -----------------------------------------------------------------------------------------------------------------------------
</span><span>
</span><span>ENABLE_SPAMASSASSIN=1
</span><span>
</span><span># add spam info headers if at, or above that level:
</span><span>SA_TAG=2.0
</span><span>
</span><span># add 'spam detected' headers at that level
</span><span>SA_TAG2=6.31
</span><span>
</span><span># triggers spam evasive actions
</span><span>SA_KILL=6.31
</span><span>
</span><span># add tag to subject if spam detected
</span><span>SA_SPAM_SUBJECT=***SPAM*****
</span><span>
</span><span># -----------------------------------------------------------------------------------------------------------------------------
</span><span># --------------------- Fetchmail section -------------------------------------------------------------------------------------
</span><span># -----------------------------------------------------------------------------------------------------------------------------
</span><span>
</span><span>ENABLE_FETCHMAIL=0
</span><span>
</span><span># The interval to fetch mail in seconds
</span><span>FETCHMAIL_POLL=300
</span><span>
</span><span># -----------------------------------------------------------------------------------------------------------------------------
</span><span># --------------------- LDAP section ------------------------------------------------------------------------------------------
</span><span># -----------------------------------------------------------------------------------------------------------------------------
</span><span>
</span><span># A second container for the ldap service is necessary (i.e. https://github.com/osixia/docker-openldap)
</span><span># For preparing the ldap server to use in combination with this container this article may be helpful: http://acidx.net/wordpress/2014/06/installing-a-mailserver-with-postfix-dovecot-sasl-ldap-roundcube/
</span><span>
</span><span># empty => LDAP authentification is disabled
</span><span># 1 => LDAP authentification is enabled
</span><span>ENABLE_LDAP=
</span><span>
</span><span># empty => no
</span><span># yes => LDAP over TLS enabled for Postfix
</span><span>LDAP_START_TLS=
</span><span>
</span><span># If you going to use the mailserver in combination with docker-compose you can set the service name here
</span><span># empty => mail.domain.com
</span><span># Specify the dns-name/ip-address where the ldap-server
</span><span>LDAP_SERVER_HOST=
</span><span>
</span><span># empty => ou=people,dc=domain,dc=com
</span><span># => e.g. LDAP_SEARCH_BASE=dc=mydomain,dc=local
</span><span>LDAP_SEARCH_BASE=
</span><span>
</span><span># empty => cn=admin,dc=domain,dc=com
</span><span># => take a look at examples of SASL_LDAP_BIND_DN
</span><span>LDAP_BIND_DN=
</span><span>
</span><span># empty** => admin
</span><span># => Specify the password to bind against ldap
</span><span>LDAP_BIND_PW=
</span><span>
</span><span># e.g. `"(&(mail=%s)(mailEnabled=TRUE))"`
</span><span># => Specify how ldap should be asked for users
</span><span>LDAP_QUERY_FILTER_USER=
</span><span>
</span><span># e.g. `"(&(mailGroupMember=%s)(mailEnabled=TRUE))"`
</span><span># => Specify how ldap should be asked for groups
</span><span>LDAP_QUERY_FILTER_GROUP=
</span><span>
</span><span># e.g. `"(&(mailAlias=%s)(mailEnabled=TRUE))"`
</span><span># => Specify how ldap should be asked for aliases
</span><span>LDAP_QUERY_FILTER_ALIAS=
</span><span>
</span><span># e.g. `"(&(|(mail=*@%s)(mailalias=*@%s)(mailGroupMember=*@%s))(mailEnabled=TRUE))"`
</span><span># => Specify how ldap should be asked for domains
</span><span>LDAP_QUERY_FILTER_DOMAIN=
</span><span>
</span><span># -----------------------------------------------------------------------------------------------------------------------------
</span><span># ---------------- Dovecot section --------------------------------------------------------------------------------------------
</span><span># -----------------------------------------------------------------------------------------------------------------------------
</span><span>
</span><span># empty => no
</span><span># yes => LDAP over TLS enabled for Dovecot
</span><span>DOVECOT_TLS=
</span><span>
</span><span># e.g. `"(&(objectClass=PostfixBookMailAccount)(uniqueIdentifier=%n))"`
</span><span>DOVECOT_USER_FILTER=
</span><span>
</span><span># e.g. `"(&(objectClass=PostfixBookMailAccount)(uniqueIdentifier=%n))"`
</span><span>DOVECOT_PASS_FILTER=
</span><span>
</span><span># -----------------------------------------------------------------------------------------------------------------------------
</span><span># ---------------- Postgrey section -------------------------------------------------------------------------------------------
</span><span># -----------------------------------------------------------------------------------------------------------------------------
</span><span>
</span><span>ENABLE_POSTGREY=0
</span><span># greylist for N seconds
</span><span>POSTGREY_DELAY=300
</span><span># delete entries older than N days since the last time that they have been seen
</span><span>POSTGREY_MAX_AGE=35
</span><span># response when a mail is greylisted
</span><span>POSTGREY_TEXT=Delayed by postgrey
</span><span># whitelist host after N successful deliveries (N=0 to disable whitelisting)
</span><span>POSTGREY_AUTO_WHITELIST_CLIENTS=5
</span><span>
</span><span># -----------------------------------------------------------------------------------------------------------------------------
</span><span># ---------------- SASL section -----------------------------------------------------------------------------------------------
</span><span># -----------------------------------------------------------------------------------------------------------------------------
</span><span>
</span><span>ENABLE_SASLAUTHD=0
</span><span>
</span><span># empty => pam
</span><span># `ldap` => authenticate against ldap server
</span><span># `shadow` => authenticate against local user db
</span><span># `mysql` => authenticate against mysql db
</span><span># `rimap` => authenticate against imap server
</span><span># NOTE: can be a list of mechanisms like pam ldap shadow
</span><span>SASLAUTHD_MECHANISMS=
</span><span>
</span><span># empty => None
</span><span># e.g. with SASLAUTHD_MECHANISMS rimap you need to specify the ip-address/servername of the imap server ==> xxx.xxx.xxx.xxx
</span><span>SASLAUTHD_MECH_OPTIONS=
</span><span>
</span><span># empty => localhost
</span><span>SASLAUTHD_LDAP_SERVER=
</span><span>
</span><span># empty or 0 => `ldap://` will be used
</span><span># 1 => `ldaps://` will be used
</span><span>SASLAUTHD_LDAP_SSL=
</span><span>
</span><span># empty => anonymous bind
</span><span># specify an object with priviliges to search the directory tree
</span><span># e.g. active directory: SASLAUTHD_LDAP_BIND_DN=cn=Administrator,cn=Users,dc=mydomain,dc=net
</span><span># e.g. openldap: SASLAUTHD_LDAP_BIND_DN=cn=admin,dc=mydomain,dc=net
</span><span>SASLAUTHD_LDAP_BIND_DN=
</span><span>
</span><span># empty => anonymous bind
</span><span>SASLAUTHD_LDAP_PASSWORD=
</span><span>
</span><span># empty => Reverting to SASLAUTHD_MECHANISMS pam
</span><span># specify the search base
</span><span>SASLAUTHD_LDAP_SEARCH_BASE=
</span><span>
</span><span># empty => default filter `(&(uniqueIdentifier=%u)(mailEnabled=TRUE))`
</span><span># e.g. for active directory: `(&(sAMAccountName=%U)(objectClass=person))`
</span><span># e.g. for openldap: `(&(uid=%U)(objectClass=person))`
</span><span>SASLAUTHD_LDAP_FILTER=
</span><span>
</span><span># empty => no
</span><span># yes => LDAP over TLS enabled for SASL
</span><span># Must not be used together with SASLAUTHD_LDAP_SSL=1_
</span><span>SASLAUTHD_LDAP_START_TLS=
</span><span>
</span><span># empty => no
</span><span># yes => Require and verify server certificate
</span><span>SASLAUTHD_LDAP_TLS_CHECK_PEER=
</span><span>
</span><span># empty => No sasl_passwd will be created
</span><span># string => `/etc/postfix/sasl_passwd` will be created with the string as password
</span><span>SASL_PASSWD=
</span><span>
</span><span># -----------------------------------------------------------------------------------------------------------------------------
</span><span># ---------------- SRS section --------------------------------------------------------------------------------------------
</span><span># -----------------------------------------------------------------------------------------------------------------------------
</span><span>
</span><span># empty => Envelope sender will be rewritten for all domains
</span><span># provide comma separated list of domains to exclude from rewriting
</span><span>SRS_EXCLUDE_DOMAINS=
</span><span>
</span><span># empty => generated when the image is built
</span><span># provide a secret to use in base64
</span><span># you may specify multiple keys, comma separated. the first one is used for
</span><span># signing and the remaining will be used for verification. this is how you
</span><span># rotate and expire keys
</span><span>SRS_SECRET=
</span><span>
</span><span># -----------------------------------------------------------------------------------------------------------------------------
</span><span># ---------------- Default relay host section ---------------------------------------------------------------------------------
</span><span># -----------------------------------------------------------------------------------------------------------------------------
</span><span>
</span><span># Setup relaying all mail through a default relay host
</span><span>#
</span><span># empty => don't configure default relay host
</span><span># default host and optional port to relay all mail through
</span><span>DEFAULT_RELAY_HOST=
</span><span>
</span><span># -----------------------------------------------------------------------------------------------------------------------------
</span><span># ---------------- Multi-domain relay section ---------------------------------------------------------------------------------
</span><span># -----------------------------------------------------------------------------------------------------------------------------
</span><span>
</span><span># Setup relaying for multiple domains based on the domain name of the sender
</span><span># optionally uses usernames and passwords in postfix-sasl-password.cf and relay host mappings in postfix-relaymap.cf
</span><span>#
</span><span># empty => don't configure relay host
</span><span># default host to relay mail through
</span><span>RELAY_HOST=
</span><span>
</span><span># empty => 25
</span><span># default port to relay mail
</span><span>RELAY_PORT=25
</span><span>
</span><span># empty => no default
</span><span># default relay username (if no specific entry exists in postfix-sasl-password.cf)
</span><span>RELAY_USER=
</span><span>
</span><span># empty => no default
</span><span># password for default relay user
</span><span>RELAY_PASSWORD=
</span></code></pre>
<p>Gitu aja, haha.</p>
<p>Untuk cek sertifikat mail server kita, bisa pakai:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo docker exec mailserver openssl s_client -connect 0.0.0.0:587 -starttls smtp -CApath /etc/ssl/certs/
</span></code></pre>
<p>Outputnya:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>...
</span><span>depth=2 O = Digital Signature Trust Co., CN = DST Root CA X3
</span><span>verify return:1
</span><span>depth=1 C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
</span><span>verify return:1
</span><span>depth=0 CN = vps.sumarsono.com
</span><span>verify return:1
</span><span>250 SMTPUTF8
</span><span>...
</span></code></pre>
<p>Cek juga untu port 25.</p>
Gogs: Self-hosted Git yang Praktis
2019-02-15T19:17:40+07:00
2019-02-15T19:17:40+07:00
Unknown
https://www.sumarsono.com/gogs-self-hosted-git-yang-praktis/
<p>Self-hosted Git? umumnya yang terlintas dibenak kita adalah Gitlab CE. Gitlab CE termasuk bagus, fiturnya banyak. Tapi, saya butuh yang sederhana, gak butuh fitur yang aneh-aneh. Gogs, jawabannya.</p>
<p>Lahirnya Golang, benar-benar membawa berkah. Gogs dibangun pakai Go, hasilnya single binary yang siap di run. Mantap kan? hahaha. Server kita tidak butuh dependensi apa-apa, kita hanya butuh database yag dibutuhkan Gogs. Lebih detail dokumentasi Dogs ada di laman <a href="https://gogs.io/docs/installation">dokumentasi Gogs</a>.</p>
<p>Untuk database, saya memilih MySql, alasannya karena ada service lain yang pakai MySql, jadi ya sekalian saja. Kemudian saya pakai Nginx untuk Webserver dan reverse proxy. Sedangkan Gogs-nya saya memilih versi docker. Kok pakai docker? bukannya Gogs tinggal run binary? Yes, exactly. Saya pakai docker karena lebih sreg aja, kebetulan saya pakai docker untuk service lain. Jadi memudahkan manajemenku sendiri. Terakhir, untuk SSL saya pakai letsencrypt.</p>
<p>Snipset reverse proxy nginx untuk Gogs:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>
</span><span>server {
</span><span> server_name git.sumarsono.com;
</span><span> #client_max_body_size 50M; # kalau upload data gede ke repo, pakai ini biar gak error
</span><span> location / {
</span><span> proxy_pass http://127.0.0.1:10017/;
</span><span> }
</span><span>
</span><span>
</span><span> listen 443 ssl; # managed by Certbot
</span><span> ssl_certificate /etc/letsencrypt/live/git.sumarsono.com/fullchain.pem; # managed by Certbot
</span><span> ssl_certificate_key /etc/letsencrypt/live/git.sumarsono.com/privkey.pem; # managed by Certbot
</span><span> include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
</span><span> ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
</span><span>
</span><span>}
</span><span>server {
</span><span> if ($host = git.sumarsono.com) {
</span><span> return 301 https://$host$request_uri;
</span><span> } # managed by Certbot
</span><span>
</span><span>
</span><span> server_name git.sumarsono.com;
</span><span> listen 80;
</span><span> return 404; # managed by Certbot
</span><span>
</span><span>
</span><span>}
</span></code></pre>
<p>Snipset docker-compose.yml:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>gogs:
</span><span> container_name: gogs
</span><span> image: gogs/gogs
</span><span> restart: always
</span><span> volumes:
</span><span> - ./gogs-data:/data
</span><span> ports:
</span><span> - "10016:22"
</span><span> - "10017:3000"
</span></code></pre>
<p>Tertarik dengan Gogs? langsung ke situs mereka saja.</p>
WebUI-Aria2: Antarmuka Aria2 Berbasis Web
2019-02-10T07:59:26+07:00
2019-02-10T07:59:26+07:00
Unknown
https://www.sumarsono.com/webui-aria2-antarmuka-aria2-berbasis-web/
<p>Disebuah group di Telegram, ada yang menyinggung aria2. Wah, belum pernah nulis artikel tentangnya, padahal sehari-hari pakai. Apa
itu aria? klik <a href="https://aria2.github.io/">disini</a>. Kalau webui-aria? silakan klik gambar diatas. Artikel ini hanya akan menunjukan cara install
webui-aria2.</p>
<p>Pertama, kita generate random token:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">openssl rand -base64 32
</span></code></pre>
<p>Kedua, kita jalankan aria2c daemon:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">aria2c --enable-rpc --rpc-listen-all --daemon --rpc-secret</span><span style="color:#b23c15;">=</span><span style="color:#282828;">token
</span></code></pre>
<p>Token silakan diganti dengan hasil random langkah pertama, walaupun sebenarnya token ini bebas sesuka kita. Hahaha.</p>
<p>Ketiga, <em>clone</em> repo webui-aria2</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">https://github.com/ziahamza/webui-aria2.git
</span></code></pre>
<p>Keempat, buka <code>index.html</code> yang ada di direktori docs hasil clone</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#b57614;">cd</span><span style="color:#282828;"> webui-aria2/docs/
</span></code></pre>
<p>Setelah terbuka dari browser, silakan klik setting > global setting, dan masukan token yang tadi dibuat
<img src="/assets/images/webui-aria2-setting.webp" alt="Setting" /></p>
<p>Selesai, silakan ber-download ria. Haha</p>
sSMTP MTA Sebagai Pengganti Sendmail dan Postfix
2019-02-08T16:42:59+07:00
2019-02-08T16:42:59+07:00
Unknown
https://www.sumarsono.com/ssmtp-mta-sebagai-pengganti-sendmail-dan-postfix/
<p>Sendmail konfigurasinya "kurang ramah", imho. Begitu juga postfix. Saya butuh sesuatu yang sederhana hanya untuk sekedar kirim email. Akhirnya saya memilih sSMTP, <em>simple beud</em>. Cukup install paket ssmtp dari repo epel. Kemudian atur konfigurasi di <code>/etc/ssmtp/ssmtp.conf</code>, kelar. Tinggal atur default pengiriman email agar pakai ssmtp dengan cara <code>alternatives --config mta</code> kemudian pilih ssmtp. Selesai.</p>
<p>contoh <code>/etc/ssmtp/ssmtp.conf</code>:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>mailhub=sub.domain.tld:587
</span><span>UseSTARTTLS=YES
</span><span>AuthUser=alamatemailmu@sumarsono.com
</span><span>AuthPass=passmu
</span></code></pre>
Docker: Roundcube Webmail
2019-02-03T14:48:51+07:00
2019-02-03T14:48:51+07:00
Unknown
https://www.sumarsono.com/docker-roundcube-webmail/
<p>Setelah seleasi setup mail server, apa selanjutnya? Webmail dong, biar kece. Haha. Untuk akses mailserver, kita bisa paka Thunderbird (desktop),
k9-Mail (android), atau lewat webmail. Opsi webmail ada banyak, roundcube, squirel, rainloop.</p>
<p>Tadi jelajah docker hub, ketemu satu yang menarik yaitu roundcube pakai nginx. Yasudah jajal itu saja.
Pertama, saya buat direktorinya dulu:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">mkdir /home/user/roundcube
</span></code></pre>
<p>Kedua, saya buat docker-compose.yml yang berisi:</p>
<pre data-lang="yaml" style="background-color:#fcf0ca;color:#282828aa;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span style="font-weight:bold;color:#407959;">roundcube</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">image</span><span>: </span><span style="color:#79740e;">robbertkl/roundcube
</span><span> </span><span style="font-weight:bold;color:#407959;">ports</span><span>:
</span><span> - </span><span style="color:#79740e;">'5001:80'
</span><span> </span><span style="font-weight:bold;color:#407959;">container_name</span><span>: </span><span style="color:#79740e;">roundcube
</span><span> </span><span style="font-weight:bold;color:#407959;">volumes</span><span>:
</span><span> - </span><span style="color:#79740e;">./roundcube-data:/var/www/db
</span><span> </span><span style="font-weight:bold;color:#407959;">environment</span><span>:
</span><span> - </span><span style="color:#79740e;">ROUNDCUBE_DEFAULT_HOST=tls://mail.domain.tld
</span><span> - </span><span style="color:#79740e;">ROUNDCUBE_SMTP_SERVER=tls://mail.domain.tld
</span><span> </span><span style="font-weight:bold;color:#407959;">restart</span><span>: </span><span style="color:#79740e;">always
</span></code></pre>
<p>Ketiga, saya menambah reverse proxy nginx untuk port 5001.
Keempat, saya up docker compose tadi.
Kelima, saya menambah CNAME record untuk webmail.</p>
<p>Selesai, silakan bukan alamat webmail dan login pakai akun yang sudah dibuat di mailserver.</p>
Docker: Setup Self-hosted Mail Server
2019-02-03T14:23:08+07:00
2019-02-03T14:23:08+07:00
Unknown
https://www.sumarsono.com/docker-setup-self-hosted-mail-server/
<p>Mail server ini ribet, konfigurasinya banyak, cakupannya luas, mulai dari MTA, MDA, etc, etc. Ribet pokoknya. Untuk meringkas semua itu, saya
memutuskan untuk memakai docker karena beruntung sudah ada yang membuat docker imagenya.</p>
<h1 id="persiapan-direktori-dan-konfigurasi">Persiapan direktori dan konfigurasi</h1>
<p>Siapkan direkori untuk mail server</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">mkdir -p /opt/dockermail/settings
</span><span style="color:#282828;">mkdir -p /opt/dockermail/mail
</span></code></pre>
<p>Buatlah config.json untuk mail server</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">nano /opt/dockermail/settings/config.json
</span></code></pre>
<p>Contoh dari config.json, silakan sesuikan domain.tld dengan yg dimiliki.</p>
<pre data-lang="json" style="background-color:#fcf0ca;color:#282828aa;" class="language-json "><code class="language-json" data-lang="json"><span>{
</span><span> </span><span style="color:#79740e;">"settings"</span><span>: {
</span><span> </span><span style="color:#79740e;">"myhostname"</span><span>: </span><span style="color:#79740e;">"hostname.domain.tld"
</span><span> },
</span><span> </span><span style="color:#79740e;">"domains"</span><span>: {
</span><span> </span><span style="color:#79740e;">"domain.tld" </span><span>:
</span><span> [
</span><span> {
</span><span> </span><span style="color:#79740e;">"email"</span><span>: </span><span style="color:#79740e;">"info@domain.tld"</span><span>,
</span><span> </span><span style="color:#79740e;">"password"</span><span>: </span><span style="color:#79740e;">"{PLAIN}tahiayam"
</span><span> },
</span><span> {
</span><span> </span><span style="color:#79740e;">"email"</span><span>: </span><span style="color:#79740e;">"admin@domain.tld"</span><span>,
</span><span> </span><span style="color:#79740e;">"password"</span><span>: </span><span style="color:#79740e;">"{PLAIN}tahiayam"</span><span>,
</span><span> </span><span style="color:#79740e;">"aliases"</span><span>: [</span><span style="color:#79740e;">"abuse@domain.tld"</span><span>, </span><span style="color:#79740e;">"webmaster@domain.tld"</span><span>, </span><span style="color:#79740e;">"postmaster@domain.tld"</span><span>]
</span><span> },
</span><span> {
</span><span> </span><span style="color:#79740e;">"email"</span><span>: </span><span style="color:#79740e;">"support@domain.tld"</span><span>,
</span><span> </span><span style="color:#79740e;">"password"</span><span>: </span><span style="color:#79740e;">"{PLAIN}tahiayam"
</span><span> },
</span><span> {
</span><span> </span><span style="color:#79740e;">"email"</span><span>: </span><span style="color:#79740e;">"abuse@domain.tld"</span><span>,
</span><span> </span><span style="color:#79740e;">"password"</span><span>: </span><span style="color:#79740e;">"{PLAIN}tahiayam"
</span><span> },
</span><span> {
</span><span> </span><span style="color:#79740e;">"email"</span><span>: </span><span style="color:#79740e;">"webmaster@domain.tld"</span><span>,
</span><span> </span><span style="color:#79740e;">"password"</span><span>: </span><span style="color:#79740e;">"{PLAIN}tahiayam"
</span><span> },
</span><span> {
</span><span> </span><span style="color:#79740e;">"email"</span><span>: </span><span style="color:#79740e;">"postmaster@domain.tld"</span><span>,
</span><span> </span><span style="color:#79740e;">"password"</span><span>: </span><span style="color:#79740e;">"{PLAIN}tahiayam"
</span><span> }
</span><span> ]
</span><span> }
</span><span>}
</span><span>
</span></code></pre>
<p>Buatlah docker-compose.yml</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">nano /opt/dockermail/settings/docker-compose.yml
</span></code></pre>
<p>Berikut ini isi dari docker-compose.yml</p>
<pre data-lang="yaml" style="background-color:#fcf0ca;color:#282828aa;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span style="font-weight:bold;color:#407959;">core</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">image</span><span>: </span><span style="color:#79740e;">adaline/dockermail-core
</span><span> </span><span style="font-weight:bold;color:#407959;">ports</span><span>:
</span><span> - </span><span style="color:#79740e;">"25:25"
</span><span> - </span><span style="color:#79740e;">"143:143"
</span><span> - </span><span style="color:#79740e;">"587:587"
</span><span> </span><span style="font-weight:bold;color:#407959;">volumes</span><span>:
</span><span> - </span><span style="color:#79740e;">/opt/dockermail/settings:/mail_settings
</span><span> - </span><span style="color:#79740e;">/opt/dockermail/mail:/vmail
</span><span> </span><span style="font-weight:bold;color:#407959;">links</span><span>:
</span><span> - </span><span style="color:#79740e;">opendkim
</span><span> - </span><span style="color:#79740e;">amavis
</span><span style="font-weight:bold;color:#407959;">opendkim</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">image</span><span>: </span><span style="color:#79740e;">adaline/dockermail-opendkim
</span><span> </span><span style="font-weight:bold;color:#407959;">volumes</span><span>:
</span><span> - </span><span style="color:#79740e;">/opt/dockermail/settings:/mail_settings
</span><span style="font-weight:bold;color:#407959;">amavis</span><span>:
</span><span> </span><span style="font-weight:bold;color:#407959;">image</span><span>: </span><span style="color:#79740e;">adaline/dockermail-amavis
</span><span> </span><span style="font-weight:bold;color:#407959;">volumes</span><span>:
</span><span> - </span><span style="color:#79740e;">/opt/dockermail/settings:/mail_settings
</span></code></pre>
<h1 id="persiapan-dns">Persiapan DNS</h1>
<p>Kita generate dkim dulu,</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#b57614;">cd</span><span style="color:#282828;"> /opt/dockermail/settings
</span><span style="color:#282828;">wget https://raw.githubusercontent.com/adaline/dockermail/master/opendkim/generate_key.sh
</span><span style="color:#282828;">bash generate_key.sh domain.tld
</span></code></pre>
<p>Catat outputnya!, akan kita pakai ketika setting dns.</p>
<p>Kemudia login ke manajemen domain dan buat record berikut ini:</p>
<table><thead><tr><th style="text-align: center">record</th><th style="text-align: center">Name</th><th style="text-align: center">Value</th></tr></thead><tbody>
<tr><td style="text-align: center">A</td><td style="text-align: center">hostname.domain.tld</td><td style="text-align: center">ip vps</td></tr>
<tr><td style="text-align: center">MX</td><td style="text-align: center">domain.tld</td><td style="text-align: center">ip vps</td></tr>
<tr><td style="text-align: center">TXT</td><td style="text-align: center">_dmarc</td><td style="text-align: center">v=DMARC1; p=quarantine; rua=mailto:postmaster@domain.tld; ruf=mailto:postmaster@domain.tld; sp=none; ri=86400</td></tr>
<tr><td style="text-align: center">TXT</td><td style="text-align: center">default._domainkey</td><td style="text-align: center">hasil generate dkim (generate_key.sh)</td></tr>
<tr><td style="text-align: center">TXT</td><td style="text-align: center">domain.tld</td><td style="text-align: center">v=spf1 a mx ip4:100.162.14.8 ~all</td></tr>
<tr><td style="text-align: center">{:.table-striped}</td><td style="text-align: center"></td><td style="text-align: center"></td></tr>
</tbody></table>
<p>Keterangan tambahan:</p>
<ul>
<li>SPF saya dapat dari mail-tester.com</li>
<li>DMARC saya dapat dari hasil mengikuti wizard di <a href="https://dmarcguide.globalcyberalliance.org/">dmarc guide</a></li>
<li>DKIM saya dapat dari generate-key.sh</li>
</ul>
<h1 id="start-instance-docker">Start instance docker</h1>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">docker-compose -f /opt/dockermail/settings/docker-compose.yml up -d
</span></code></pre>
<p>didalam folder /opt/dockermail/settings/ akan muncul ssl cert dan key:</p>
<ul>
<li>ssl-cert-snakeoil.key</li>
<li>ssl-cert-snakeoil.pem</li>
</ul>
<p>silakan direplace pakai sertifikat lets encrypt, saya buat dengan cara <code>certbot --nginx</code> kemudian memilih domain domain.tld</p>
<p>Untuk enkripsi password:
<code>docker ps</code>, cari nama container email kita, selanjutnya:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">docker exec -it nama-kontainer doveadm pw -s SHA512-CRYPT
</span><span style="color:#282828;">Enter new password: password yg mau dipakai
</span><span style="color:#282828;">Retype new password: konfirmasi password yg mau dipakai
</span><span style="color:#282828;">{SHA512-CRYPT</span><span>}</span><span style="color:#282828;">random-string-hasil-enkripsi
</span></code></pre>
<p>Setelah password yang diperlukan dibuat, silakan update password masing-masing akun yang ada di config.json</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">nano /opt/dockermail/settings/config.json
</span></code></pre>
<p>Contohnya begini:</p>
<pre data-lang="json" style="background-color:#fcf0ca;color:#282828aa;" class="language-json "><code class="language-json" data-lang="json"><span>{
</span><span> </span><span style="color:#79740e;">"settings"</span><span>: {
</span><span> </span><span style="color:#79740e;">"myhostname"</span><span>: </span><span style="color:#79740e;">"vps.domain.tld"
</span><span> },
</span><span> </span><span style="color:#79740e;">"domains"</span><span>: {
</span><span> </span><span style="color:#79740e;">"domain.tld" </span><span>:
</span><span> [
</span><span> {
</span><span> </span><span style="color:#79740e;">"email"</span><span>: </span><span style="color:#79740e;">"info@domain.tld"</span><span>,
</span><span> </span><span style="color:#79740e;">"password"</span><span>: </span><span style="color:#79740e;">"{SHA512-CRYPT}random-string-hasil-enkripsi"
</span><span> },
</span><span> {
</span><span> </span><span style="color:#79740e;">"email"</span><span>: </span><span style="color:#79740e;">"admin@domain.tld"</span><span>,
</span><span> </span><span style="color:#79740e;">"password"</span><span>: </span><span style="color:#79740e;">"{SHA512-CRYPT}random-string-hasil-enkripsi"</span><span>,
</span><span> </span><span style="color:#79740e;">"aliases"</span><span>: [</span><span style="color:#79740e;">"abuse@domain.tld"</span><span>, </span><span style="color:#79740e;">"webmaster@domain.tld"</span><span>, </span><span style="color:#79740e;">"postmaster@domain.tld"</span><span>]
</span><span> },
</span><span> {
</span><span> </span><span style="color:#79740e;">"email"</span><span>: </span><span style="color:#79740e;">"support@domain.tld"</span><span>,
</span><span> </span><span style="color:#79740e;">"password"</span><span>: </span><span style="color:#79740e;">"{SHA512-CRYPT}random-string-hasil-enkripsi"
</span><span> },
</span><span> {
</span><span> </span><span style="color:#79740e;">"email"</span><span>: </span><span style="color:#79740e;">"abuse@domain.tld"</span><span>,
</span><span> </span><span style="color:#79740e;">"password"</span><span>: </span><span style="color:#79740e;">"{SHA512-CRYPT}random-string-hasil-enkripsi"
</span><span> },
</span><span> {
</span><span> </span><span style="color:#79740e;">"email"</span><span>: </span><span style="color:#79740e;">"webmaster@domain.tld"</span><span>,
</span><span> </span><span style="color:#79740e;">"password"</span><span>: </span><span style="color:#79740e;">"{SHA512-CRYPT}random-string-hasil-enkripsi"
</span><span> },
</span><span> {
</span><span> </span><span style="color:#79740e;">"email"</span><span>: </span><span style="color:#79740e;">"postmaster@domain.tld"</span><span>,
</span><span> </span><span style="color:#79740e;">"password"</span><span>: </span><span style="color:#79740e;">"{SHA512-CRYPT}random-string-hasil-enkripsi"
</span><span> }
</span><span> ]
</span><span> }
</span><span>}
</span></code></pre>
<p>Kemudian restart docker instance</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">docker-compose -f /opt/dockermail/settings/docker-compose.yml restart
</span></code></pre>
<p>Kemudian kita tes email server kita, saya memanfaatkan <a href="https://www.mail-tester.com/">mail-tester</a> nampak seperti gambar pembuka artikel ini. Dari
sana apa yang kurang bisa kita
sesuaikan.</p>
Upgrade SailfishOS Mido ke Sipoonkorpi (3.0.1.11)
2019-02-02T10:32:41+07:00
2019-02-02T10:32:41+07:00
Unknown
https://www.sumarsono.com/upgrade-sailfishos-mido-ke-sipoonkorpi-3-0-1-11/
<p>Artikel sebelum ini kan sudah bahas cara install, sekarang cara upgrade. Mudah kok,</p>
<ul>
<li>Masuk ke setting developer option.</li>
<li>Set root password</li>
<li>Buka terminal:</li>
</ul>
<p>Dapatkan akses root:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>devel-su # kemudian masukan passwd tadi
</span></code></pre>
<p>Lakukan chroot</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>chroot /
</span></code></pre>
<p>masuk ke direktori repo:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>cd usr/share/ssu/features.d
</span></code></pre>
<p>Edit file <code>adaptation-community.ini</code> ganti url dengan:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>http://repo.merproject.org/obs/nemo:/devel:/hw:/xiaomi:/mido/sailfishos_3.0.1.11/
</span></code></pre>
<p>Edit file <code>adaptation-community-common.ini</code> ganti url dengan:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>http://repo.merproject.org/obs/nemo:/devel:/hw:/common/sailfishos_3.0.1.11/
</span></code></pre>
<p>Eksekusi proses update:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>ssu re 3.0.1.11
</span><span>
</span><span>ssu ur
</span><span>
</span><span>zypper ref
</span><span>
</span><span>zypper dup
</span></code></pre>
<p>Ada sekitar 300MB (500++ file) yang harus didownload. Setelah selesai, silakan reboot HP.</p>
<p>Skrinsut:</p>
<script async src="https://telegram.org/js/telegram-widget.js?5" data-telegram-post="unomindgithubio/8" data-width="100%"></script>
Panduan Install Sailfish OS di Redmi Note 4x (Mido)
2019-02-02T10:19:34+07:00
2019-02-02T10:19:34+07:00
Unknown
https://www.sumarsono.com/panduan-install-sailfish-os-di-redmi-note-4x-mido/
<p>Sailfish OS? ya. OS alternatif dari Jolla, bukan android. Jadi ya jangan harap ada APK. Apakah bagus? so far so good dan menarik untuk dicoba.</p>
<h2 id="apa-yang-kita-butuhkan">Apa yang kita butuhkan?</h2>
<ul>
<li>HP Mido dan tentu sudah UBL</li>
<li><a href="https://dl.twrp.me/mido/">TWRP Recovery versi 3.2.2.0</a>, jangan pakai yang treble.</li>
<li><a href="https://www.androidfilehost.com/?fid=817906626617953644">Custom Rom CM14</a></li>
<li><a href="https://gitlab.com/sailfishos-porters-ci/mido-ci/-/jobs/118711673/artifacts/download">Artefak SailfishOS</a>, ekstrak dulu setelah download</li>
</ul>
<h2 id="cara-install">Cara install</h2>
<ul>
<li>Install TWRP</li>
<li>Masuk TWRP</li>
<li>Format data (Format ya, bukan sekedar wipe)</li>
<li>Install CM14</li>
<li>Install SailfishOS</li>
<li>Reboot</li>
<li>Have Fun</li>
</ul>
<h2 id="skrinsut">Skrinsut?</h2>
<p>Skrinsut aku jadikan satu di artikel [upgrade sailfish os]({% post_url 2019-02-02-upgrade-sailfishos-mido-ke-sipoonkorpi-(3.0.1.11) %})</p>
Mengatasi Journal Systemd yang Bengkak
2019-02-01T10:19:14+07:00
2019-02-01T10:19:14+07:00
Unknown
https://www.sumarsono.com/mengatasi-journal-systemd-yang-bengkak/
<p>Pagi ini saya terperangah karena tiba-tiba, serverku disk usagenya lebih besar dari yang seharusnya. Kemudian saya telusuri pakai <code>ncdu</code>
untuk mendapatkan ada dimana direktori yang bengkak. Akhirnya ketemu di <code>/var/log/journal/</code>, 4GB. <em>OMG</em>.</p>
<p>Baiklah saya verifikasi itu size pakai <code>journalctl --disk-usage</code>, beneran 4GB. Akhirnya saya cek journald.conf, oalah masih dipagar semua,
tidak ada batasan. Saya edit <code>/etc/systemd/journald.conf</code> diisi dengan:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>[Journal]
</span><span>Storage=auto
</span><span>SystemMaxUse=400M
</span><span>SystemMaxFileSize=30M
</span><span>RuntimeMaxUse=250M
</span><span>RuntimeMaxFileSize=30M
</span></code></pre>
<p>Kemudian saya hapus journal yang lama <code>find /var/log/journal -name "*.journal" | xargs sudo rm</code>. Kemudian restart service journalnya,
<code>systemctl restart systemd-journald</code> dilanjutkan dengan verifikasi, untuk memastikan tidak ada yang korup, <code>journalctl --verify</code>.</p>
<p>terakhir, cek disk-usage dan sudah aman. Kita tunggu sekian hari lagi dan pastikan tidak bengkak. Oh iya saya lupa kasih info server, saya
pakai AWS EC2 dengan OS AWS AMI 2.</p>
<p>Semoga bermanfaat.</p>
Docker: MySQL 5.7 dan Phpmyadmin
2019-01-28T12:46:12+07:00
2019-01-28T12:46:12+07:00
Unknown
https://www.sumarsono.com/docker-mysql-5-7-dan-phpmyadmin/
<p>Hari ini mau main-main sama MySQL, tapi saya tidak mau mengotori system. Jadi, docker adalah pilihan yang tepat.
Saya membutuhkan mysql:5.7 dan phpmyadmin/phpmyadmin.</p>
<p>Pertama, saya pull dan run mysql:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">docker pull mysql:5.7
</span><span style="color:#282828;">docker run --name mysqlku -e MYSQL_ROOT_PASSWORD=passwdku -d mysql:5.7
</span></code></pre>
<p>Selanjutnya, saya pull dan run phpmyadmin/phpmyadmin, tentu saja saya link ke mysqlku:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">docker pull phpmyadmin/phpmyadmin
</span><span style="color:#282828;">docker docker run --name myadmin --link mysqlku:db -p 8080:80 -d phpmyadmin/phpmyadmin
</span></code></pre>
<p>Selesai. Untuk akses phpmyadmin, silakan buka browser dan pergi ke http://localhost:8080. Login pakai user <code>root</code> dan passwd <code>passwordku</code>.
<img src="/assets/images/phpmyadmin.webp" alt="phpmyadmin.webp" /></p>
<blockquote>
<p>Note:</p>
</blockquote>
<p>Kalau ada kendala gagal login, silakan coba untuk masuk container mysqlku dengan cara:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">docker exec -it mysqlku bash
</span></code></pre>
<p>Kemudian eksekusi command <code>mysql -u root -p</code> dan eksekusi query berikut ini:
sql
alter user 'root'@'localhost' identified with mysql_native_password by 'passwordku';</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code></code></pre>
Delete Log Older Than x Days
2019-01-25T13:21:35+07:00
2019-01-25T13:21:35+07:00
Unknown
https://www.sumarsono.com/delete-log-older-than-x-days/
<p>Saya bingung mau menulis judulnya, hahaha. Intinya begini, saya punya banyak file log, ada ratusan. File tersebut sebagian sudah tidak
diperlukan. Saya ingin menghapus semua file yang last updatenya lebih dari seminggu lalu (older than 7 Days).</p>
<p>Caranya adalah pakai <em>find</em>. Hapus-hapus file begini riskan, resiko salah hapus. Jadi simulasikan dulu:</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">find /path/dir/berisi/log -mtime +7 type f
</span></code></pre>
<p>Maksud command diatas adalah menampilkan daftar file yg older than 7 days dari direktori <code>/path/dir/berisi/log</code>. Kalau sudah yakin itu
file-filenya, kita tambahkan <em>delete</em>.</p>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">find /path/dir/berisi/log -mtime +7 type f -delete
</span></code></pre>
<p>Selesai, yang penting hati-hati dan hapus file yang benar.</p>
Tomcat X Nginx: Reverse Proxy
2019-01-23T08:24:23+07:00
2019-01-23T08:24:23+07:00
Unknown
https://www.sumarsono.com/tomcat-x-nginx-reverse-proxy/
<p>Tomcat7 di Centos 7 tidak bisa bind port 80. Lagipula, bukan <em>best practice</em> serve langsung pakai tomcat. Oleh sebab itu, di depan tomcat harus ada web server lain, bisa apache httpd, bisa juga Nginx. Artikel ini hanya akan berisi <em>snipset</em> konfigurasi reverse proxy tomcat pakai nginx.</p>
<p>Snipset Nginx vhost:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>###
</span><span># Desc: Nginx reserve proxy untuk aplikasi servlet tomcat
</span><span># Author: Sumarsono
</span><span># Create date: 2019-01-08
</span><span># Tested: Yes
</span><span>##
</span><span>
</span><span>server {
</span><span> listen 80;
</span><span> server_name sub.domain.tld;
</span><span>
</span><span> error_log /var/log/nginx/sub/error.log warn;
</span><span> access_log /var/log/nginx/sub/access.log combined;
</span><span>
</span><span> location / {
</span><span> proxy_set_header Host $host;
</span><span> proxy_set_header X-Forwarded-Host $host;
</span><span> proxy_set_header X-Forwarded-Server $host;
</span><span> proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
</span><span> proxy_pass http://localhost:8080/;
</span><span> }
</span><span>}
</span></code></pre>
<p>Snipset server.xml:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>...
</span><span><Engine name="Catalina" defaultHost="localhost">
</span><span> <Valve className="org.apache.catalina.valves.RemoteIpValve"
</span><span> internalProxies="127\.0\.[0-1]\.1"
</span><span> remoteIpHeader="x-forwarded-for"
</span><span> requestAttributesEnabled="true"
</span><span> protocolHeader="x-forwarded-proto"
</span><span> protocolHeaderHttpsValue="https"/>
</span><span>...
</span></code></pre>
<p>Selesai.</p>
Handel Webhook Github Menggunakan Golang
2019-01-20T06:16:23+07:00
2019-01-20T06:16:23+07:00
Unknown
https://www.sumarsono.com/handel-webhook-github-menggunakan-golang/
<p>Sebelumnya sudah saya tulis tentang webhook github dan di handle pakai Flask. Ketika saya browsing-browsing, saya menemukan sesuatu yang menarik, yaitu <a href="https://github.com/go-playground/webhooks">library Golang untuk handel webhook</a> dari github. Setelah melihat example dari reponya, wah layak dicoba, sederhana dan mudah di implementasi.</p>
<p>Saya putuskan untuk mengganti program dari python dan flask, dengan Golang. Flownya sih masih sama:</p>
<p>Ketika terjadi event push di repo github maka VPS akan melakukan pull, rebuild jekyll, dan deploy ke production.</p>
<p>Baiklah langsung saja</p>
<h2 id="pertama-saya-membuat-direktori-kerja">Pertama saya membuat direktori kerja</h2>
<p>Begini susunannya:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>go
</span><span>└── src
</span><span> └── jekhook
</span><span> ├── jekhook
</span><span> ├── main.go
</span><span> └── rebuild.sh
</span></code></pre>
<ul>
<li>jekhook: nanti muncul setelah kita melakukan go build</li>
<li>main.go: Source code golang untuk handel webhook github</li>
<li>rebuild.sh: bash script untuk pull, rebuild, dan deploy jekyll</li>
</ul>
<h2 id="unduh-library-pendukung">Unduh library pendukung</h2>
<p>Dalam hal ini saya memakai library webhooks.v5, sangat membantu.</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>go get -u gopkg.in/go-playground/webhooks.v5
</span></code></pre>
<h2 id="tulis-program-main-go">Tulis program main.go</h2>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>nano go/src/main.go
</span></code></pre>
<p>Isinya adalah:</p>
<pre data-lang="go" style="background-color:#fcf0ca;color:#282828aa;" class="language-go "><code class="language-go" data-lang="go"><span style="color:#9d0006;">package </span><span style="color:#282828;">main
</span><span>
</span><span style="color:#9d0006;">import </span><span>(
</span><span> </span><span style="color:#79740e;">"fmt"
</span><span> </span><span style="color:#79740e;">"net/http"
</span><span> </span><span style="color:#79740e;">"gopkg.in/go-playground/webhooks.v5/github"
</span><span> </span><span style="color:#79740e;">"os/exec"
</span><span> </span><span style="color:#79740e;">"log"
</span><span>)
</span><span>
</span><span style="color:#9d0006;">const </span><span>(
</span><span> </span><span style="color:#282828;">path </span><span style="color:#b23c15;">= </span><span style="color:#79740e;">"/webhooks"
</span><span>)
</span><span>
</span><span style="color:#9d0006;">func </span><span style="color:#407959;">main</span><span>() {
</span><span> </span><span style="color:#282828;">hook</span><span>, </span><span style="color:#282828;">_ </span><span style="color:#b23c15;">:= </span><span style="color:#282828;">github</span><span>.</span><span style="color:#282828;">New</span><span>(</span><span style="color:#282828;">github</span><span>.</span><span style="color:#282828;">Options</span><span>.</span><span style="color:#282828;">Secret</span><span>(</span><span style="color:#79740e;">"secret webhook kamu"</span><span>))
</span><span>
</span><span> </span><span style="color:#282828;">http</span><span>.</span><span style="color:#282828;">HandleFunc</span><span>(</span><span style="color:#282828;">path</span><span>, </span><span style="color:#9d0006;">func</span><span>(</span><span style="color:#282828;">w http</span><span>.</span><span style="color:#9d0006;">ResponseWriter</span><span>, </span><span style="color:#282828;">r </span><span style="color:#b23c15;">*</span><span style="color:#282828;">http</span><span>.</span><span style="color:#9d0006;">Request</span><span>) {
</span><span> </span><span style="color:#282828;">payload</span><span>, </span><span style="color:#282828;">err </span><span style="color:#b23c15;">:= </span><span style="color:#282828;">hook</span><span>.</span><span style="color:#282828;">Parse</span><span>(</span><span style="color:#282828;">r</span><span>, </span><span style="color:#282828;">github</span><span>.</span><span style="color:#282828;">PushEvent</span><span>) </span><span style="font-style:italic;color:#928374;">//github.ReleaseEvent, github.PullRequestEvent, github.PushEvent
</span><span> </span><span style="color:#9d0006;">if </span><span style="color:#282828;">err </span><span style="color:#b23c15;">!= </span><span style="color:#8f3f71;">nil </span><span>{
</span><span> </span><span style="color:#9d0006;">if </span><span style="color:#282828;">err </span><span style="color:#b23c15;">== </span><span style="color:#282828;">github</span><span>.</span><span style="color:#282828;">ErrEventNotFound </span><span>{
</span><span> </span><span style="font-style:italic;color:#928374;">// ok event wasn;t one of the ones asked to be parsed
</span><span> }
</span><span> }
</span><span> </span><span style="color:#9d0006;">switch </span><span style="color:#282828;">payload</span><span>.(</span><span style="color:#9d0006;">type</span><span>) {
</span><span> </span><span style="color:#9d0006;">case </span><span style="color:#282828;">github</span><span>.</span><span style="color:#282828;">PushPayload</span><span>:
</span><span> </span><span style="color:#282828;">cmd</span><span>, </span><span style="color:#282828;">err </span><span style="color:#b23c15;">:= </span><span style="color:#282828;">exec</span><span>.</span><span style="color:#282828;">Command</span><span>(</span><span style="color:#79740e;">"/bin/bash"</span><span>, </span><span style="color:#79740e;">"rebuild.sh"</span><span>).</span><span style="color:#282828;">Output</span><span>()
</span><span> </span><span style="color:#9d0006;">if </span><span style="color:#282828;">err </span><span style="color:#b23c15;">!= </span><span style="color:#8f3f71;">nil </span><span>{
</span><span> </span><span style="color:#282828;">log</span><span>.</span><span style="color:#282828;">Fatal</span><span>(</span><span style="color:#282828;">err</span><span>)
</span><span> }
</span><span> </span><span style="color:#282828;">fmt</span><span>.</span><span style="color:#282828;">Printf</span><span>(</span><span style="color:#79740e;">"</span><span style="color:#282828;">%s</span><span style="color:#79740e;">\n"</span><span>, </span><span style="color:#282828;">cmd</span><span>)
</span><span> }
</span><span> })
</span><span> </span><span style="color:#282828;">http</span><span>.</span><span style="color:#282828;">ListenAndServe</span><span>(</span><span style="color:#79740e;">"127.0.0.1:5000"</span><span>, </span><span style="color:#8f3f71;">nil</span><span>)
</span><span>}
</span></code></pre>
<p>Untuk bagian <code>secret webhook kamu</code> silakan sesuaikan.</p>
<p>Saya memakai ip 127.0.0.1 dengan port 5000, nantinya saya harus melakukan reverse proxy ke port tersebut. Saya juga memakai path <code>/webhooks</code> sehingga reverse proxy harus ke 127.0.0.1:5000/webhooks</p>
<h2 id="tulis-bash-script-rebuild-sh">Tulis bash script rebuild.sh</h2>
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="font-style:italic;color:#928374;">#!/bin/bash
</span><span style="color:#b57614;">source</span><span style="color:#282828;"> /home/sumarsono/.rvm/scripts/rvm</span><span style="color:#b23c15;">;
</span><span>
</span><span style="color:#b57614;">cd </span><span style="color:#282828;">~/blog/nalakawula.github.io</span><span style="color:#b23c15;">;
</span><span>
</span><span style="color:#b57614;">echo </span><span style="color:#79740e;">"pulling new post"</span><span style="color:#b23c15;">;
</span><span style="color:#282828;">git pull origin master</span><span style="color:#b23c15;">;
</span><span>
</span><span style="color:#b57614;">echo </span><span style="color:#79740e;">"rebuild site"</span><span style="color:#b23c15;">;
</span><span style="color:#282828;">bundle exec jekyll build</span><span style="color:#b23c15;">;
</span><span>
</span><span style="color:#b57614;">echo </span><span style="color:#79740e;">"deploying to production"
</span><span style="color:#282828;">cp -rf ~/blog/nalakawula.github.io/_site/</span><span style="color:#b23c15;">*</span><span style="color:#282828;"> /var/www/html/sumarsono/</span><span style="color:#b23c15;">;
</span></code></pre>
<h2 id="lakukan-build">Lakukan build</h2>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>cd go/src/jekhook/
</span><span>go build
</span></code></pre>
<p>Akan muncul satu file executable bernama jekhook.</p>
<h2 id="konfigurasi-nginx">konfigurasi nginx</h2>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>server {
</span><span>
</span><span> listen 80;
</span><span>
</span><span> root /var/www/html/api/;
</span><span> server_name api.sumarsono.com;
</span><span>
</span><span> error_log /var/log/nginx/api/error.log warn;
</span><span> access_log /var/log/nginx/api/access.log combined;
</span><span>
</span><span> location /webhooks {
</span><span> proxy_set_header Host $host;
</span><span> proxy_set_header X-Forwarded-Host $host;
</span><span> proxy_set_header X-Forwarded-Server $host;
</span><span> proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
</span><span> proxy_pass http://localhost:5000/webhooks;
</span><span> }
</span><span>
</span></code></pre>
<p>Jangan lupa reload nginx</p>
<h2 id="jalankan-jekhook">jalankan jekhook</h2>
<p>Hasil dari <code>go build</code> adalah file bernama jekhook, kita jalankan file tersebut:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>./jekhook
</span></code></pre>
<h2 id="konfigurasi-webhook-di-repo-github">konfigurasi webhook di repo github</h2>
<p>Untuk konfigurasinya, seperti gambar dibawah ini:
<img src="/assets/images/gh-webhook2.webp" alt="gh-webhook.webp" /></p>
<h2 id="coba-untuk-push">Coba untuk push</h2>
<p>Perhatikan repon di server VPS, seharusnya begini:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>pulling new post
</span><span>Updating d579392..2351df6
</span><span>Fast-forward
</span><span> webhook-test | 2 --
</span><span> webhook-test.txt | 0
</span><span> 2 files changed, 2 deletions(-)
</span><span> delete mode 100644 webhook-test
</span><span> create mode 100644 webhook-test.txt
</span><span>rebuild site
</span><span>Configuration file: /home/sumarsono/blog/nalakawula.github.io/_config.yml
</span><span> Source: /home/sumarsono/blog/nalakawula.github.io
</span><span> Destination: /home/sumarsono/blog/nalakawula.github.io/_site
</span><span> Incremental build: disabled. Enable with --incremental
</span><span> Generating...
</span><span> Jekyll Feed: Generating feed for posts
</span><span> done in 2.884 seconds.
</span><span> Auto-regeneration: disabled. Use --watch to enable.
</span><span>deploying to production
</span></code></pre>
<p>Selesai, tinggal run jekhook di background dan leyeh-leyeh.</p>
Continuous Integration Sederhana Jekyll dan Github Webhook
2019-01-19T05:17:59+07:00
2019-01-19T05:17:59+07:00
Unknown
https://www.sumarsono.com/continuous-integration-sederhana-jekyll-dan-github-webhook/
<p>Saya tidak tahu apakah ini bisa disebut sebagai Continuous Integration. Hahaha. Flownya seperti gambar diatas. Untuk casenya seperti ini:</p>
<ul>
<li>Saya punya VPS dan serving website yang dibuild pakai jekyll di dalamnya.</li>
<li>Repo dari situs itu saya simpan di github.</li>
<li>Selama ini, dari dalam vps saya pull dan build secara manual.</li>
<li>Saya ingin pull otomatis, jekyll build otomatis, dan deploy hasil build secara otomatis, ketika saya melakukan push ke repo yang ada di github.</li>
</ul>
<p>Solusinya adalah:</p>
<ul>
<li>Github webhook</li>
<li>Sesuatu di VPS yang akan menerima webhook (saya akan pakai flask dan bash script).</li>
</ul>
<h2 id="saya-buat-program-flask-untuk-merespon-webhook-dari-github">Saya buat program flask untuk merespon webhook dari github</h2>
<pre data-lang="python" style="background-color:#fcf0ca;color:#282828aa;" class="language-python "><code class="language-python" data-lang="python"><span style="color:#9d0006;">from </span><span>flask </span><span style="color:#9d0006;">import </span><span>Flask, request
</span><span style="color:#9d0006;">import </span><span>subprocess
</span><span style="color:#9d0006;">import </span><span>os
</span><span style="color:#9d0006;">import </span><span>json
</span><span>
</span><span>app </span><span style="color:#b23c15;">= </span><span style="color:#282828;">Flask(</span><span style="color:#b57614;">__name__</span><span style="color:#282828;">)
</span><span>
</span><span>@app.</span><span style="color:#282828;">route</span><span>(</span><span style="color:#79740e;">'/'</span><span>, </span><span style="color:#282828;">methods</span><span style="color:#b23c15;">=</span><span>[</span><span style="color:#79740e;">'POST'</span><span>])
</span><span style="color:#9d0006;">def </span><span style="color:#407959;">blogrefresh</span><span>():
</span><span> data </span><span style="color:#b23c15;">= </span><span style="color:#282828;">json.loads(request.data)
</span><span> </span><span style="color:#9d0006;">print </span><span style="color:#79740e;">"New commit by: </span><span style="color:#282828;">{}</span><span style="color:#79740e;">"</span><span style="color:#282828;">.format(data[</span><span style="color:#79740e;">'commits'</span><span style="color:#282828;">][</span><span style="color:#8f3f71;">0</span><span style="color:#282828;">][</span><span style="color:#79740e;">'author'</span><span style="color:#282828;">][</span><span style="color:#79740e;">'name'</span><span style="color:#282828;">])
</span><span>
</span><span> script_path </span><span style="color:#b23c15;">= </span><span style="color:#79740e;">"/home/sumarsono/jekyll_rebuild.sh"
</span><span> </span><span style="color:#282828;">subprocess.call([os.path.expanduser(script_path)])
</span><span> </span><span style="color:#9d0006;">return </span><span style="color:#79740e;">"OK"
</span><span>
</span><span style="color:#9d0006;">if </span><span style="color:#b57614;">__name__ </span><span style="color:#b23c15;">== </span><span style="color:#79740e;">"__main__"</span><span>:
</span><span> </span><span style="color:#282828;">app.run(host</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">"127.0.0.1"</span><span style="color:#282828;">, port</span><span style="color:#b23c15;">=</span><span style="color:#8f3f71;">5000</span><span style="color:#282828;">)
</span></code></pre>
<p>Disitu saya memakai library <code>flask</code>, saya install pakai <code>pip</code>. Kemudian ada bash script yang dieksekusi yaitu <code>jekyll_rebuild.sh</code>, harus dibuat.</p>
<h2 id="bash-script-untuk-build-dan-deploy-jekyll">Bash script untuk build dan deploy jekyll</h2>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">nano /home/sumarsono/jekyll_rebuild.sh
</span></code></pre>
<p>Isinya:</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="font-style:italic;color:#928374;">#!/bin/bash
</span><span style="color:#b57614;">source</span><span style="color:#282828;"> /home/sumarsono/.rvm/scripts/rvm
</span><span>
</span><span style="color:#b57614;">cd </span><span style="color:#282828;">~/blog/anuan</span><span style="color:#b23c15;">;
</span><span style="color:#282828;">git pull origin master</span><span style="color:#b23c15;">;
</span><span style="color:#282828;">bundle exec jekyll build</span><span style="color:#b23c15;">;
</span><span style="color:#282828;">cp -rf ~/blog/anuan/_site/</span><span style="color:#b23c15;">*</span><span style="color:#282828;"> /var/www/html/sumarsono/</span><span style="color:#b23c15;">;
</span></code></pre>
<h2 id="konfigurasi-vhost-nginx">Konfigurasi vhost nginx</h2>
<p>Saya tidak mau membuka port 5000 ke public, jadi pakai reserve proxy aja buat ngarahin ke localhost:5000</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>server {
</span><span> listen 80;
</span><span> server_name api.anuan.com;
</span><span>
</span><span> error_log /var/log/nginx/api/error.log warn;
</span><span> access_log /var/log/nginx/api/access.log combined;
</span><span>
</span><span> location /jekyll {
</span><span> proxy_set_header Host $host;
</span><span> proxy_set_header X-Forwarded-Host $host;
</span><span> proxy_set_header X-Forwarded-Server $host;
</span><span> proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
</span><span> proxy_set_header Host $host;
</span><span> proxy_pass http://localhost:5000/;
</span><span> }
</span><span>}
</span></code></pre>
<p>Nantinya, setiap akses ke api.anuan.com/jekyll akan di proxy ke localhost:5000. Jangan lupa reload nginx, <code>nginx -s reload</code> dan tambahkan subdomain api di manager dns.</p>
<h2 id="eksekusi">eksekusi</h2>
<p>siapkan repo di lokal</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">mkdir /home/sumarsono/blog
</span><span style="color:#b57614;">cd</span><span style="color:#282828;"> /home/sumarsono/blog
</span><span style="color:#282828;">git clone git clone git@github.com:unomind/anuan.git
</span></code></pre>
<p>Jalankan program python tadi:</p>
<pre data-lang="python" style="background-color:#fcf0ca;color:#282828aa;" class="language-python "><code class="language-python" data-lang="python"><span>python </span><span style="color:#b23c15;">/</span><span>home</span><span style="color:#b23c15;">/</span><span>sumarsono</span><span style="color:#b23c15;">/</span><span>webhook.py
</span></code></pre>
<p>Konfigurasi webhook di repo github
<img src="/assets/images/gh-webhook.webp" alt="gh-webhook.webp" /></p>
<p>Kalau kita coba melakukan push ke repo, VPS kita akan menanggapinya kurang lebih seperti ini:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>remote: Enumerating objects: 7, done.
</span><span>remote: Counting objects: 100% (7/7), done.
</span><span>remote: Compressing objects: 100% (1/1), done.
</span><span>remote: Total 4 (delta 3), reused 4 (delta 3), pack-reused 0
</span><span>Unpacking objects: 100% (4/4), done.
</span><span>From github.com:unomind/nalakawula.github.io
</span><span> * branch master -> FETCH_HEAD
</span><span>Updating 0920d54..73fbf41
</span><span>Fast-forward
</span><span> _posts/2019-01-18-pembaruan-otomatis-sertifikat-lets-encrypt-menggunakan-systemd-timer.md | 2 +-
</span><span> 1 file changed, 1 insertion(+), 1 deletion(-)
</span><span>Configuration file: /home/sumarsono/blog/anuan/_config.yml
</span><span> Source: /home/sumarsono/blog/anuan
</span><span> Destination: /home/sumarsono/blog/anuan/_site
</span><span> Incremental build: disabled. Enable with --incremental
</span><span> Generating...
</span><span> Jekyll Feed: Generating feed for posts
</span><span> done in 3.059 seconds.
</span><span> Auto-regeneration: disabled. Use --watch to enable.
</span><span>127.0.0.1 - - [19/Jan/2019 05:13:53] "POST / HTTP/1.0" 200 -
</span></code></pre>
<p>PR selanjutnya adalah menambahkan secret.</p>
Pembaruan Otomatis Sertifikat Lets Encrypt Menggunakan Systemd Timer
2019-01-18T08:42:29+07:00
2019-01-18T08:42:29+07:00
Unknown
https://www.sumarsono.com/pembaruan-otomatis-sertifikat-lets-encrypt-menggunakan-systemd-timer/
<p>Pakai let's encrypt? untuk banyak domain? masa iya mau mengingat-ingat satu demi satu kapan harus renew. Merepotkan, dibikin otomatis saja.</p>
<p>Saya pakai let's encrypt untuk berbagai domain dan sub domain, setupnya gini:</p>
<ul>
<li>Nginx sebagai webserver</li>
<li>Certbot sebagai generator sertifikat let's encrypt</li>
</ul>
<p>Cara renewal otomatis?</p>
<h2 id="bikin-service-systemd">bikin service systemd</h2>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">nano /etc/systemd/system/certbot-renewal.service
</span></code></pre>
<p>Isinya begini:</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">[Unit]
</span><span style="color:#282828;">Description</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">Renew </span><span style="color:#282828;">certificates
</span><span>
</span><span style="color:#282828;">[Service]
</span><span style="color:#282828;">Type</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">oneshot
</span><span style="color:#282828;">ExecStart</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">/bin/certbot </span><span style="color:#282828;">renew --post-hook </span><span style="color:#79740e;">"/sbin/nginx -s reload"</span><span style="color:#282828;"> --quiet
</span></code></pre>
<h2 id="bikin-timer-systemd">bikin timer systemd</h2>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">nano /etc/systemd/system/certbot-renewal.timer
</span></code></pre>
<p>Isinya begini:</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">[Unit]
</span><span style="color:#282828;">Description</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">Twice </span><span style="color:#282828;">daily check for cert renewal
</span><span>
</span><span style="color:#282828;">[Timer]
</span><span style="color:#282828;">OnCalendar</span><span style="color:#b23c15;">=*</span><span style="color:#79740e;">-</span><span style="color:#b23c15;">*</span><span style="color:#79740e;">-</span><span style="color:#b23c15;">* </span><span style="color:#282828;">06,18:09:00
</span><span style="color:#282828;">Persistent</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">true
</span><span>
</span><span style="color:#282828;">[Install]
</span><span style="color:#282828;">WantedBy</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">timers.target
</span></code></pre>
<h2 id="enable-service-dan-timer-tadi">Enable service dan timer tadi</h2>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">systemctl enable certbot-renewal.service
</span><span style="color:#282828;">systemctl enable certbot-renewal.timer
</span></code></pre>
<h2 id="start-timer">start timer</h2>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">systemctl start certbot-renewal.timer
</span></code></pre>
<h2 id="cek-status-timer">cek status timer</h2>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">systemctl list-timers --all
</span></code></pre>
<p>Hasilnya kira-kira begini:</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">NEXT LEFT LAST PASSED UNIT ACTIVATES
</span><span style="color:#282828;">Fri 2019-01-18 11:23:24 WIB 2h 53min left Thu 2019-01-17 11:23:24 WIB 21h ago systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.service
</span><span style="color:#282828;">Fri 2019-01-18 18:09:00 WIB 9h left n/a n/a certbot-renewal.timer certbot-renewal.service
</span><span style="color:#282828;">n/a n/a n/a n/a systemd-readahead-done.timer systemd-readahead-done.service
</span><span>
</span><span style="color:#282828;">3 timers listed.
</span></code></pre>
<p>Selesai. Semoga bermanfaat. Ditunggu feedback-nya.</p>
My Current Manjaro Look
2019-01-14T15:27:33+07:00
2019-01-14T15:27:33+07:00
Unknown
https://www.sumarsono.com/my-current-manjaro-look/
<pre data-lang="bash" style="background-color:#fcf0ca;color:#282828aa;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#282828;">sumarsono@NUC:~$ screenfetch
</span><span>
</span><span> </span><span style="color:#282828;">██████████████████ ████████ sumarsono@NUC
</span><span> </span><span style="color:#282828;">██████████████████ ████████ OS: Manjaro 18.0.2 Illyria
</span><span> </span><span style="color:#282828;">██████████████████ ████████ Kernel: x86_64 Linux 4.19.13-1-MANJARO
</span><span> </span><span style="color:#282828;">██████████████████ ████████ Uptime: 4h 1m
</span><span> </span><span style="color:#282828;">████████ ████████ Packages: 1211
</span><span> </span><span style="color:#282828;">████████ ████████ ████████ Shell: bash 4.4.23
</span><span> </span><span style="color:#282828;">████████ ████████ ████████ Resolution: 1366x768
</span><span> </span><span style="color:#282828;">████████ ████████ ████████ DE: KDE 5.53.0 / Plasma 5.14.4
</span><span> </span><span style="color:#282828;">████████ ████████ ████████ WM: KWin
</span><span> </span><span style="color:#282828;">████████ ████████ ████████ GTK Theme: Breath </span><span style="color:#9d0006;">[</span><span style="color:#282828;">GTK2/3</span><span style="color:#9d0006;">]
</span><span> </span><span style="color:#282828;">████████ ████████ ████████ Icon Theme: maia
</span><span> </span><span style="color:#282828;">████████ ████████ ████████ Font: Noto Sans Regular
</span><span> </span><span style="color:#282828;">████████ ████████ ████████ CPU: Intel Core i3-5010U @ 4x 2GHz </span><span style="color:#9d0006;">[</span><span style="color:#282828;">46.0°C</span><span style="color:#9d0006;">]
</span><span> </span><span style="color:#282828;">████████ ████████ ████████ GPU: Mesa DRI Intel(R</span><span>) </span><span style="color:#282828;">HD Graphics 5500 (Broadwell GT2</span><span>)
</span><span> </span><span style="color:#282828;">RAM: 2900MiB / 3828MiB
</span></code></pre>
<p>Additional:</p>
<ul>
<li>Latte Dock</li>
<li>appmenu-gtk-module</li>
<li>Active Window Control Widget</li>
<li>Other? just downloaded from store.kde.org</li>
</ul>
Konfigurasi Wireguard Server dan Klien
2019-01-10T13:21:04+07:00
2019-01-10T13:21:04+07:00
Unknown
https://www.sumarsono.com/konfigurasi-wireguard-server-dan-klien/
<p>Melanjutkan artikel <a href="https://nalakawula.github.io/2019/01/10/install-wireguard-vpn-di-vps-centos-7.5-linode/">install wireguard</a>. Sekarang saatnya konfigurasi biar bisa dipakai.</p>
<p>Untuk konfiguras akan saya bagi menjadi dua bagian, bagian server dan klien. Masing-masing memiliki konfigurasi sebagai berikut:</p>
<h2 id="server">Server</h2>
<ol>
<li>OS Centos 7.5 dengan kernel 4.20</li>
<li>Terpasang wireguard</li>
<li>Lokasi: VPS Linode singapura</li>
</ol>
<h2 id="klien">Klien</h2>
<ol>
<li>OS Manjaro dengan kernel 4.18</li>
<li>Terpasang wireguard</li>
<li>Lokasi: lokal</li>
</ol>
<h1 id="konfigurasi">Konfigurasi</h1>
<h2 id="1-server">1. Server</h2>
<h3 id="bikin-folder-untuk-menyimpan-konfigurasi">Bikin folder untuk menyimpan konfigurasi</h3>
<p>Folder ini untuk menyimpan konfigurasi wireguard</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">mkdir -p /etc/wireguard
</span><span style="color:#b57614;">cd</span><span style="color:#282828;"> /etc/wireguard
</span></code></pre>
<h3 id="generate-key-pair">Generate key-pair</h3>
<p>Kita harus generate keypair server dan klien</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#b57614;">umask</span><span style="color:#282828;"> 077
</span><span style="color:#282828;">wg genkey </span><span style="color:#b23c15;">| </span><span style="color:#282828;">tee server_private.key </span><span style="color:#b23c15;">| </span><span style="color:#282828;">wg pubkey </span><span style="color:#b23c15;">></span><span style="color:#282828;"> server_public.key
</span><span style="color:#282828;">wg genkey </span><span style="color:#b23c15;">| </span><span style="color:#282828;">tee client_private.key </span><span style="color:#b23c15;">| </span><span style="color:#282828;">wg pubkey </span><span style="color:#b23c15;">></span><span style="color:#282828;"> client_public.key </span><span style="color:#b23c15;">| </span><span style="color:#282828;">wg genpsk </span><span style="color:#b23c15;">></span><span style="color:#282828;"> client_psk.key
</span></code></pre>
<h3 id="bikin-konfigurasi-untuk-server">Bikin konfigurasi untuk server</h3>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">nano /etc/wireguard/wg0.conf
</span></code></pre>
<p>Isinya sbb:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>[Interface]
</span><span>Address = 10.200.200.4/24
</span><span>PrivateKey = <insert server_private.key>
</span><span>ListenPort = 34777
</span><span>
</span><span>[Peer]
</span><span>PublicKey = <insert client_public.key>
</span><span>PresharedKey = <client_psk.key>
</span><span>AllowedIPs = 10.200.200.2/32
</span></code></pre>
<p>/32 artinya hanya satu ip address.</p>
<h3 id="jalankan-wireguard">jalankan wireguard</h3>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">wg-quick up wg0
</span></code></pre>
<h3 id="enable-ip-forwarding">enable IP forwarding</h3>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#b57614;">echo</span><span style="color:#282828;"> 1 </span><span style="color:#b23c15;">></span><span style="color:#282828;"> /proc/sys/net/ipv4/ip_forward
</span><span style="color:#282828;">sysctl -p
</span></code></pre>
<h3 id="setting-firewall">setting firewall</h3>
<p>Saya pakai firewall cmd, pertama bikin masquerade rule</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">firewall-cmd --permanent --add-rich-rule</span><span style="color:#b23c15;">=</span><span style="color:#79740e;">'rule family=ipv4 source address=10.200.200.4/24 masquerade'
</span></code></pre>
<p>Kemudian bikin rule untuk accept forwarding dari wg0 ke eth0</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">firewall-cmd --permanent --direct --add-rule ipv4 filter FORWARD 0 -i wg0 -o eth0 -j ACCEPT
</span></code></pre>
<p>Selanjutnya kita buka port 34777/udp</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">firewall-cmd --permanent --zone</span><span style="color:#b23c15;">=</span><span style="color:#282828;">public --add-port</span><span style="color:#b23c15;">=</span><span style="color:#282828;">34777/udp
</span></code></pre>
<p>Selanjutnya, kita tambahkan interface wg0 ke zone public</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">firewall-cmd --zone</span><span style="color:#b23c15;">=</span><span style="color:#282828;">public --add-interface</span><span style="color:#b23c15;">=</span><span style="color:#282828;">wg0 --permanent
</span></code></pre>
<p>Terakhir, reload firewall-cmd</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">firewall-cmd --reload
</span></code></pre>
<h2 id="2-klien">2. Klien</h2>
<p>Sisi server sudah selesai, selanjutnya konfigurasi klien</p>
<h3 id="bikin-folder-untuk-menyimpan-konfigurasi-1">Bikin folder untuk menyimpan konfigurasi</h3>
<p>Folder ini untuk menyimpan konfigurasi wireguard</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">mkdir -p /etc/wireguard
</span><span style="color:#b57614;">cd</span><span style="color:#282828;"> /etc/wireguard
</span></code></pre>
<h3 id="bikin-konfigurasi-untuk-klien">Bikin konfigurasi untuk klien</h3>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">nano /etc/wireguard/wg0-client.conf
</span></code></pre>
<p>Isinya sbb:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>[Interface]
</span><span>Address = 10.200.200.5/24
</span><span>PrivateKey = <insert client_private.key>
</span><span>DNS = 8.8.8.8
</span><span>
</span><span>[Peer]
</span><span>PublicKey = <insert server_public.key>
</span><span>PresharedKey = <client_psk.key, klien dan server harus sama>
</span><span>Endpoint = <ip public server>:34777
</span><span>AllowedIPs = 0.0.0.0/0
</span><span>PersistentKeepalive = 21
</span></code></pre>
<h3 id="start-wireguard">Start wireguard</h3>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">wg-quick up wg0-client
</span></code></pre>
<p>Selesai, coba tes ping dari klien ke server pakai ip address wireguard:</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">[NUC wireguard]# ping -c 5 10.200.200.4
</span><span style="color:#282828;">PING 10.200.200.4 (10.200.200.4</span><span>) </span><span style="color:#282828;">56(84</span><span>) </span><span style="color:#282828;">bytes of data.
</span><span style="color:#282828;">64 bytes from 10.200.200.4: icmp_seq=1 ttl=64 time=61.5 ms
</span><span style="color:#282828;">64 bytes from 10.200.200.4: icmp_seq=2 ttl=64 time=75.5 ms
</span><span style="color:#282828;">64 bytes from 10.200.200.4: icmp_seq=3 ttl=64 time=72.3 ms
</span><span style="color:#282828;">64 bytes from 10.200.200.4: icmp_seq=4 ttl=64 time=66.3 ms
</span><span style="color:#282828;">64 bytes from 10.200.200.4: icmp_seq=5 ttl=64 time=37.6 ms
</span><span>
</span><span style="color:#282828;">--- 10.200.200.4 ping statistics ---
</span><span style="color:#282828;">5 packets transmitted, 5 received, 0% packet loss, time 9ms
</span><span style="color:#282828;">rtt min/avg/max/mdev = 37.618/62.657/75.464/13.411 ms
</span></code></pre>
<p>Kalau server ke klien?</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">[sumarsono@vps ~]$ ping -c 5 10.200.200.5
</span><span style="color:#282828;">PING 10.200.200.5 (10.200.200.5</span><span>) </span><span style="color:#282828;">56(84</span><span>) </span><span style="color:#282828;">bytes of data.
</span><span style="color:#282828;">64 bytes from 10.200.200.5: icmp_seq=1 ttl=64 time=35.2 ms
</span><span style="color:#282828;">64 bytes from 10.200.200.5: icmp_seq=2 ttl=64 time=72.3 ms
</span><span style="color:#282828;">64 bytes from 10.200.200.5: icmp_seq=3 ttl=64 time=45.8 ms
</span><span style="color:#282828;">64 bytes from 10.200.200.5: icmp_seq=4 ttl=64 time=74.5 ms
</span><span style="color:#282828;">64 bytes from 10.200.200.5: icmp_seq=5 ttl=64 time=43.8 ms
</span><span>
</span><span style="color:#282828;">--- 10.200.200.5 ping statistics ---
</span><span style="color:#282828;">5 packets transmitted, 5 received, 0% packet loss, time 4006ms
</span><span style="color:#282828;">rtt min/avg/max/mdev = 35.290/54.376/74.501/15.978 ms
</span><span style="color:#282828;">[sumarsono@vps ~]$
</span></code></pre>
<p>Mudah bukan? ada yg keliru? jangan sungkan komentar, gratis.
Oh iya, konfigurasi di atas merupakan contoh ya, jadi kalau mau dipakai sesuaikan dulu. Selebihnya silakan merujuk ke wiki wireguard.</p>
Install Wireguard VPN di VPS Centos 7.5 Linode
2019-01-10T11:40:43+07:00
2019-01-10T11:40:43+07:00
Unknown
https://www.sumarsono.com/install-wireguard-vpn-di-vps-centos-7-5-linode/
<p>Wireguard VPN ini merupakan sesuatu yang baru. Menariknya dia lebih gegas dibandingkan dengan pendahulunya, openvpn. Hasil dari benchmark klik <a href="https://www.wireguard.com/performance/">disini</a>.</p>
<p>Satu hal yang kurang menarik dari wireguard adalah proses installnya, setidaknya untuk saat ini. Hal tersebut karena harus menyentuh kernel. Nah, Centos 7.5 di Linode masih pakai kernel 3.10, belum support. Yasudah kesempatan bagus upgrade kernel sekalian coba wireguard. Hahaha.</p>
<p>Untuk detail installnya kita butuh:</p>
<ol>
<li>Menambahkan repo kernel-ml</li>
<li>Menambahkan repo wireguard</li>
<li>Install latest LTS Kernel, beserta kernel-headernya dan paket kernel-develnya (kernel-ml, kernel-ml-headers, kernel-ml-devel).</li>
<li>Install wireguard-tools dan wireguard-dkms.</li>
</ol>
<p>Baiklah, dimulai saja dengan ssh ke VPS:</p>
<h2 id="menambahkan-repo-kernel-ml">Menambahkan repo kernel-ml</h2>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
</span><span style="color:#282828;">rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-2.el7.elrepo.noarch.rpm
</span></code></pre>
<h2 id="menambahkan-repo-wireguard">Menambahkan repo wireguard</h2>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">curl -Lo /etc/yum.repos.d/wireguard.repo https://copr.fedorainfracloud.org/coprs/jdoss/wireguard/repo/epel-7/jdoss-wireguard-epel-7.repo
</span></code></pre>
<h2 id="install-kernel-lts-terbaru">Install kernel LTS terbaru</h2>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">yum --enablerepo</span><span style="color:#b23c15;">=</span><span style="color:#282828;">elrepo-kernel install kernel-ml kernel-ml-headers kernel-ml-devel
</span></code></pre>
<h2 id="install-wireguard">install wireguard</h2>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">yum install wireguard-dkms wireguard-tools
</span></code></pre>
<p>Sampai sini, wireguard sudah terinstall. Berikutnya adalah konfigurasi dan ujicoba, akan saya tulis di artikel lain.</p>
Load Balancing Tomcat Menggunakan Nginx
2019-01-08T19:38:14+07:00
2019-01-08T19:38:14+07:00
Unknown
https://www.sumarsono.com/load-balancing-tomcat-menggunakan-nginx/
<p>Apa itu load balancing? Mengutip dari situs nginx:
Load balancing refers to efficiently distributing incoming network traffic across a group of backend servers, also known as a server farm or server pool.
Selengkapnya klik <a href="https://www.nginx.com/resources/glossary/load-balancing/">disini</a></p>
<p>Berikut ini adalah contoh load balancing aplikasi tomcat:
Skenario:</p>
<ul>
<li>ada dua buah server dengan tomcat berjalan di dalamnya.</li>
<li>masing-masing tomcat berjalan di port 8080.</li>
<li>setiap akses ke contoh.com akan di proxy ke upstream backend.</li>
</ul>
<p>Berikut ini adalah konfigurasi nginxnya:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>###
</span><span># Desc: Load balancing aplikasi servlet tomcat, menggunakan nginx
</span><span># Author: Sumarsono
</span><span># Create date: 2019-01-08
</span><span># Tested: Yes
</span><span>##
</span><span>
</span><span>proxy_cache_path /tmp/NGINX_cache/ keys_zone=backcache:10m;
</span><span>
</span><span>map $http_upgrade $connection_upgrade {
</span><span> default upgrade;
</span><span> '' close;
</span><span>}
</span><span>
</span><span>upstream tomcat {
</span><span> # Use IP Hash for session persistence
</span><span> ip_hash;
</span><span>
</span><span> # List of Tomcat application servers
</span><span> #server 10.100.100.11:8080;
</span><span> #server 10.100.100.12:8080;
</span><span>
</span><span> #server+app tomcat 1
</span><span> server 14.252.14.28:8080;
</span><span>
</span><span> #server+app tomcat 2
</span><span> server 14.252.14.20:8080;
</span><span>}
</span><span>
</span><span>server {
</span><span> listen 80;
</span><span> server_name contoh.com;
</span><span>
</span><span> # Load balance requests for / across Tomcat application servers
</span><span> location / {
</span><span> proxy_pass http://tomcat;
</span><span> proxy_cache backcache;
</span><span> proxy_set_header Host $host;
</span><span> proxy_set_header X-Forwarded-Host $host;
</span><span> proxy_set_header X-Forwarded-Server $host;
</span><span> proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
</span><span> }
</span><span>
</span><span> # WebSocket configuration
</span><span> location /wstunnel/ {
</span><span> proxy_pass https://tomcat;
</span><span> proxy_http_version 1.1;
</span><span> proxy_set_header Upgrade $http_upgrade;
</span><span> proxy_set_header Connection $connection_upgrade;
</span><span> }
</span><span>}
</span></code></pre>
Tahun baru tampilan baru
2019-01-06T14:25:41+07:00
2019-01-06T14:25:41+07:00
Unknown
https://www.sumarsono.com/tahun-baru-tampilan-baru/
<p>Tahun 2019, menulis resolusi sudah terlalu umum. Akhirnya kuputuskan untuk mengganti tampilan <a href="https://nalakawula.github.io">static site ini</a>.</p>
<p>Dulu, situs ini pakai tampilan yang sama dengan <a href="https://rizaumami.github.io/">situs</a> punya mimin pegelinux. Alasannya karena saya suka tampilan situs beliau, simple, tanpa <strong>gimmick</strong>. Akhirnya saya minta ijin untuk nge-clone repo beliau dan dijinkan. Walaupun tidak sepenuhnya sama, karena saya menambahkan beberapa fitur seperti pagination, emoji, dst. </p>
<p>Tapi hari ini saya ingin pakai yang beda, karena bosan. haha. Akhirnya ketemu tema jekyll bernama Mediumish. Dengan sedikit otak atik sana sini agar sesuai dengan keinginan saya, lahirlah tampilan yang sekarang.</p>
<p>Gimana? cakep kan? hahaha.</p>
uji coba maps api
2018-11-29T11:21:37+07:00
2018-11-29T11:21:37+07:00
Unknown
https://www.sumarsono.com/uji-coba-maps-api/
<iframe
width="600"
height="450"
frameborder="0" style="border:0"
src="https://www.google.com/maps/embed/v1/place?key=AIzaSyB73BzNYohKRTqDMrLP4yUfyJ_-nGWkasg
&q=Space+Needle,Seattle+WA" allowfullscreen>
</iframe>
Batch Rename File's Extension from Bash
2018-11-08T10:08:02+07:00
2018-11-08T10:08:02+07:00
Unknown
https://www.sumarsono.com/batch-rename-file-s-extension-from-bash/
<p>Untuk suatu keperluan, terkadang kita perlu melakukan <strong>batch</strong> rename untuk banyak file. Dalam kasus ini saya ingin rename file dengan ekstensi yang seragam, dan outputnya juga seragam. Yaitu *.log menjadi *.md.</p>
<p>Untuk praktik, kita bisa membuat file yang banyak terlebih dahulu, misalnya 1.log - 50.log</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">mkdir latihan
</span><span>
</span><span style="color:#b57614;">cd</span><span style="color:#282828;"> latihan
</span></code></pre>
<p>jalankan skrip dibawah ini, untuk membuat file 1.log - 50.log. Jadi nanti akan ada 50 file:</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#9d0006;">for</span><span> i </span><span style="color:#9d0006;">in </span><span>{1..50}</span><span style="color:#b23c15;">; </span><span style="color:#9d0006;">do </span><span style="color:#282828;">touch $i.log</span><span style="color:#b23c15;">; </span><span style="color:#9d0006;">done
</span></code></pre>
<p>kalau di <code>ls</code>:</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">[orangtua@mesintua latihan]$ ls
</span><span style="color:#282828;">10.log 13.log 16.log 19.log 21.log 24.log 27.log 2.log 32.log 35.log 38.log 40.log 43.log 46.log 49.log 5.log 8.log
</span><span style="color:#282828;">11.log 14.log 17.log 1.log 22.log 25.log 28.log 30.log 33.log 36.log 39.log 41.log 44.log 47.log 4.log 6.log 9.log
</span><span style="color:#282828;">12.log 15.log 18.log 20.log 23.log 26.log 29.log 31.log 34.log 37.log 3.log 42.log 45.log 48.log 50.log 7.log
</span></code></pre>
<p>Sekarang saatnya batch rename:</p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#9d0006;">for</span><span> file </span><span style="color:#9d0006;">in </span><span style="color:#b23c15;">*</span><span>.log</span><span style="color:#b23c15;">; </span><span style="color:#9d0006;">do </span><span style="color:#282828;">mv </span><span style="color:#79740e;">"$</span><span style="color:#282828;">file</span><span style="color:#79740e;">" "$(</span><span style="color:#282828;">basename </span><span style="color:#79740e;">"$</span><span style="color:#282828;">file</span><span style="color:#79740e;">"</span><span style="color:#282828;"> .log</span><span style="color:#79740e;">).md"</span><span style="color:#b23c15;">; </span><span style="color:#9d0006;">done
</span></code></pre>
<p>Kalau di <code>ls</code></p>
<pre data-lang="sh" style="background-color:#fcf0ca;color:#282828aa;" class="language-sh "><code class="language-sh" data-lang="sh"><span style="color:#282828;">[orangtua@mesintua latihan]$ ls
</span><span style="color:#282828;">10.md 13.md 16.md 19.md 21.md 24.md 27.md 2.md 32.md 35.md 38.md 40.md 43.md 46.md 49.md 5.md 8.md
</span><span style="color:#282828;">11.md 14.md 17.md 1.md 22.md 25.md 28.md 30.md 33.md 36.md 39.md 41.md 44.md 47.md 4.md 6.md 9.md
</span><span style="color:#282828;">12.md 15.md 18.md 20.md 23.md 26.md 29.md 31.md 34.md 37.md 3.md 42.md 45.md 48.md 50.md 7.md
</span></code></pre>
<p>Semoga bermanfaat</p>
GRUB Remember Last Choice
2018-10-14T20:27:57+07:00
2018-10-14T20:27:57+07:00
Unknown
https://www.sumarsono.com/grub-remember-last-choice/
<p>Informasi konfigurasi grub dapat diakses melalui perintah <code>info -f grub -n 'Simple Configurtaion'</code>. Untuk membuat grub menyimpan pilihan terakhir, kita harus menyunting berkas <code>/etc/default/grub</code>, </p>
<ol>
<li>edit baris <code>GRUB_DEFAULT=0</code> menjadi <code>GRUB_DEFAULT=saved</code></li>
<li>Tambahkan baris <code>GRUB_SAVEDEFAULT=true</code>
Secara keseluruhan berikut ini milik saya:</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>GRUB_DEFAULT=saved
</span><span>GRUB_SAVEDEFAULT=true
</span><span>GRUB_TIMEOUT_STYLE=hidden
</span><span>GRUB_TIMEOUT=10
</span><span>GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian`
</span><span>GRUB_CMDLINE_LINUX_DEFAULT="splash quiet"
</span><span>GRUB_CMDLINE_LINUX=""
</span></code></pre>
<ol start="3">
<li>Update grub, kalau keluarga debian bisa pakai <code>update-grub</code>, kalau fedora bisa pakai <code>grub-mkconfig</code></li>
</ol>
Cek Badblock pada Partisi EMMC Android
2018-10-10T18:40:47+07:00
2018-10-10T18:40:47+07:00
Unknown
https://www.sumarsono.com/cek-badblock-pada-partisi-emmc-android/
<p>Seprti pada umumnya NAND Flash yang sering ditulis, pasti akan mencapai masa muncul <em>bad block</em>. Kalau di HDD sih <em>bad sector</em>. Demikian juga EMMC HP kita. Kebiasaanku yang gonta-ganti custom firmware, gonta-ganti dari <em>filesystem</em>, mungkin menyebabkan <em>bad block</em> pada EMMC. Nah, dalam tulisan ini akan saya tulis bagaimana saya cek <em>bad block</em> di HP saya.</p>
<p>Untuk kasus saya, HP yang saya pakai adalah Redmi Note 4 Snapdragon a.k.a Mido. Reno4 ada dua varian berdasarkan prosesornya, MTK (Nikel) dan Qualcomm (Mido). Berikut ini langkah demi langkah yang saya tempuh:</p>
<ol>
<li>Reboot HP ke TWRP</li>
<li>Masuk ke menu Andvanced > Terminal</li>
<li>Pindah direktori: </li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>cd /dev/block/platform/soc/[chipID]/by-name
</span></code></pre>
<p>dalam kasus saya:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>/dev/block/platform/soc/7824900.sdhci/by-name
</span></code></pre>
<ol start="4">
<li>Unmount partisi yang akan di cek, misalnya <code>userdata</code></li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>umount userdata
</span></code></pre>
<ol start="5">
<li>Cek <em>bad block</em></li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>e2fsck -cfv userdata
</span></code></pre>
<p>Info lebih tentang e2fsck bisa akses <code>e2fsk --help</code></p>
Bikin Distro Linux Menggunakan RTC daripada UTC
2018-10-09T19:05:55+07:00
2018-10-09T19:05:55+07:00
Unknown
https://www.sumarsono.com/bikin-distro-linux-menggunakan-rtc-daripada-utc/
<p>Secara <em>default</em> Distribusi GNU/Linux menggunakan patokan UTC untuk <em>date time</em>. Ya bukan masalah sih, tapi kadang jadi mengganggu kalau dualboot dengan sistem operasi besutan Microsoft. Untuk mengetahui apakah sistem kita menggunakan UTC ataukah RTC, bisa gunakan salah satu fitur dari <code>systemd</code>:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>orangtua@mesin-tua:~/nalakawula.github.io$ timedatectl status
</span><span> Local time: Tue 2018-10-09 19:08:23 WIB
</span><span> Universal time: Tue 2018-10-09 12:08:23 UTC
</span><span> RTC time: Tue 2018-10-09 12:08:21
</span><span> Time zone: Asia/Jakarta (WIB, +0700)
</span><span> System clock synchronized: yes
</span><span>systemd-timesyncd.service active: yes
</span><span> RTC in local TZ: no
</span><span>
</span></code></pre>
<p>Kalau mau supaya memakai RTC, tinggal eksekusi:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>timedatectl set-local-rtc 1 --adjust-system-clock
</span></code></pre>
<p>Nanti hasilnya begini:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>orangtua@mesin-tua:~/nalakawula.github.io$ timedatectl status
</span><span> Local time: Tue 2018-10-09 19:08:23 WIB
</span><span> Universal time: Tue 2018-10-09 12:08:23 UTC
</span><span> RTC time: Tue 2018-10-09 12:08:21
</span><span> Time zone: Asia/Jakarta (WIB, +0700)
</span><span> System clock synchronized: yes
</span><span>systemd-timesyncd.service active: yes
</span><span> RTC in local TZ: yes
</span><span>
</span><span>Warning: The system is configured to read the RTC time in the local time zone.
</span><span> This mode can not be fully supported. It will create various problems
</span><span> with time zone changes and daylight saving time adjustments. The RTC
</span><span> time is never updated, it relies on external facilities to maintain it.
</span><span> If at all possible, use RTC in UTC by calling
</span><span> 'timedatectl set-local-rtc 0'.
</span></code></pre>
<p>Mudah kan?</p>
Embed Pesan Telegram ke Post Jekyll
2018-09-29T13:13:42+07:00
2018-09-29T13:13:42+07:00
Unknown
https://www.sumarsono.com/embed-pesan-telegram-ke-post-jekyll/
<p>Langsung kemari saja <a href="https://core.telegram.org/widgets/posts">https://core.telegram.org/widgets/posts</a> pasti langsung mengerti.</p>
<p>Contoh hasilnya:</p>
<ul>
<li><a href="https://nalakawula.github.io/2018/09/27/sailfish-os-untuk-mido/">https://nalakawula.github.io/2018/09/27/sailfish-os-untuk-mido/</a></li>
<li><a href="https://nalakawula.github.io/2018/09/29/menjalankan-aplikasi-android-di-sailfish-os/">https://nalakawula.github.io/2018/09/29/menjalankan-aplikasi-android-di-sailfish-os/</a></li>
</ul>
Ekstrak Semua Tautan dari Sebuah Website Menggunakan Lynx
2018-09-29T13:06:34+07:00
2018-09-29T13:06:34+07:00
Unknown
https://www.sumarsono.com/ekstrak-semua-tautan-dari-sebuah-website-menggunakan-lynx/
<p>Ini adalah cara yang <em>masokis</em>, menggunakan terminal dan <code>lynx</code>. Langsung ke contoh saja, pasti langsung paham</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>orangtua@mesin-tua:~/$ lynx -listonly -dump nalakawula.github.io
</span><span>
</span><span>References
</span><span>
</span><span> Visible links
</span><span> 1. https://nalakawula.github.io/feed.xml
</span><span> 2. https://nalakawula.github.io/
</span><span> 3. https://nalakawula.github.io/about/
</span><span> 4. https://nalakawula.github.io/contact/
</span><span> 5. https://nalakawula.github.io/2018/09/29/menjalankan-aplikasi-android-di-sailfish-os/
</span><span> 6. https://nalakawula.github.io/2018/09/27/sailfish-os-untuk-mido/
</span><span> 7. https://nalakawula.github.io/2018/09/17/shelter-isolate-your-big-brother-app-multiple-accounts/
</span><span> 8. https://nalakawula.github.io/2018/07/02/setelah-install-windows-10/
</span><span> 9. https://nalakawula.github.io/2018/07/01/free-upgrade-windows-7-pro-oem-ke-windows-10/
</span><span> 10. https://nalakawula.github.io/2018/06/30/move-on,-life-must-go-on/
</span><span> 11. https://nalakawula.github.io/2018/06/29/selamat-idulfitri/
</span><span> 12. https://nalakawula.github.io/2018/03/27/mencicipi-miui-global-dev/
</span><span> 13. https://nalakawula.github.io/2018/03/19/mengganti-ip-standar-ics-windows-7/
</span><span> 14. https://nalakawula.github.io/2018/02/02/kamera-bokeh-ala-ala-google-camera/
</span><span> 15. https://nalakawula.github.io/2018/01/29/client-to-server-c2s-port-forwarding-menggunakan-bitvise-ssh-client/
</span><span> 16. https://nalakawula.github.io/2018/01/18/setup-vagrant-di-windows-7-pro-x64/
</span><span> 17. https://nalakawula.github.io/2018/01/18/aktivasi-windows-7-pro-oem-melalui-jalur-telepon/
</span><span> 18. https://nalakawula.github.io/2017/12/17/autocutoff-charging-menggunakan-arduino/
</span><span> 19. https://nalakawula.github.io/2017/12/01/resize-aplikasi-microsoft-office-2010-di-wine/
</span><span> 20. https://nalakawula.github.io/2017/12/01/menautkan-kalender-google-ke-korganizer-kde/
</span><span> 21. https://nalakawula.github.io/2017/11/28/instalasi-microsoft-office-2010-di-debian-9/
</span><span> 22. https://nalakawula.github.io/2017/11/24/virtualbox-mengatasi-nerwork-adapter-2-tidak-mendapatkan-ip-address-dari-dhcp-server/
</span><span> 23. https://nalakawula.github.io/2017/11/10/kde-yang-sekarang-bukan-kde-yang-dulu/
</span><span> 24. https://nalakawula.github.io/2017/11/05/telegram-desktop-multiple-instances/
</span><span> 25. https://nalakawula.github.io/2017/10/29/mudah-konversi-skema-gpt-ke-mbr/
</span><span> 26. https://nalakawula.github.io/2017/10/27/jekyll-trik-untuk-image-caption/
</span><span> 27. https://nalakawula.github.io/2017/10/24/mudah-bypass-password-windows-10/
</span><span> 28. https://nalakawula.github.io/2017/10/17/mengatasi-error-import-gobject-ketika-menjalankan-hp-setup-di-arch-linux/
</span><span> 29. https://nalakawula.github.io/2017/10/01/setup-raspberry-pi-super-headless/
</span><span> 30. https://nalakawula.github.io/2017/09/30/mencoba-jekyll-admin/
</span><span> 31. https://nalakawula.github.io/2017/09/30/pengalalaman-belanja-di-aliexpress-pembayaran-menggunakan-debit-btn/
</span><span> 32. https://nalakawula.github.io/2017/09/27/share-koneksi-internet-wifi-via-ethernet-di-arch-linux/
</span><span> 33. https://nalakawula.github.io/2017/09/21/repositori-sublime-text-untuk-arch-linux/
</span><span> 34. https://nalakawula.github.io/2017/09/20/postrouting-openwrt/
</span><span> 35. https://nalakawula.github.io/2017/09/19/tp-link-mr3420-v3-eu-wds-mode-dengan-firmware-lede/
</span><span> 36. https://nalakawula.github.io/2017/08/16/i3wm-second-display-only/
</span><span> 37. https://nalakawula.github.io/2017/08/16/install-firmware-berbasis-openwrt-di-tp-link-mr3420-v3-eu/
</span><span> 38. https://nalakawula.github.io/2017/08/16/debrick-tp-link-mr3420-v3-eu-yang-gagal-flash-firmware-berbasis-openwrt/
</span><span> 39. https://nalakawula.github.io/2017/08/14/mudah-download-xcode-9-beta-5-dengan-resume-support/
</span><span> 40. https://nalakawula.github.io/2017/07/27/laptop-dengan-kerusakan-pada-cpu-s-decoupling-capacitor/
</span><span> 41. https://nalakawula.github.io/2017/07/26/mengatasi-reminder-aktifasi-office-365-yang-muncul-berulang-ulang/
</span><span> 42. https://nalakawula.github.io/2017/07/17/mengatasi-galat-can-t-open-device-dev-ttyacm0-permission-denied-ketika-upload-program-ke-arduino-dari-arch-linux/
</span><span> 43. https://nalakawula.github.io/2017/07/16/akses-android-mtp-di-os-x/
</span><span> 44. https://nalakawula.github.io/2017/07/13/mudah-mencari-driver-printer-canon-dengan-cepat/
</span><span> 45. https://nalakawula.github.io/2017/07/13/google-chrome-standalone-installer/
</span><span> 46. https://nalakawula.github.io/2017/07/05/mudah-dualboot-remix-os-dengan-arch-linux/
</span><span> 47. https://nalakawula.github.io/2017/07/04/backup-partisi-root-arch-linux-menggunakan-gnome-disk/
</span><span> 48. https://nalakawula.github.io/2017/06/27/backup-bootloader-arch-linux/
</span><span> 49. https://nalakawula.github.io/2017/06/26/ada-yang-salah-dengan-idulfitri-ku/
</span><span> 50. https://nalakawula.github.io/2017/06/10/k-9-mail-dan-verifikasi-dua-langkah-google/
</span><span> 51. https://nalakawula.github.io/2017/05/29/menambah-indonesia-di-setting-region-language-arch-linux/
</span><span> 52. https://nalakawula.github.io/2017/05/27/pacman-cheat-sheet/
</span><span> 53. https://nalakawula.github.io/2017/05/27/jekyll-di-arch-linux/
</span><span> 54. https://nalakawula.github.io/2017/05/25/mencoba-layanan-netlify/
</span><span> 55. https://nalakawula.github.io/2017/05/25/hari-yang-panas/
</span><span> 56. https://nalakawula.github.io/2017/05/25/mengganti-akes-github-dari-https-ke-ssh/
</span><span> 57. https://nalakawula.github.io/2017/05/25/menambah-tag-dalam-situs-jekyll/
</span><span> 58. https://nalakawula.github.io/2017/05/24/membuat-tautan-referensi-ke-artikel-lain-dalam-jekyll/
</span><span> 59. https://nalakawula.github.io/2017/05/22/memasang-wall-facelet-cat5e-panasonic/
</span><span> 60. https://nalakawula.github.io/2017/05/21/jekyll-plugin-untuk-atom/
</span><span> 61. https://nalakawula.github.io/2017/05/20/atom,-powerfull-markdown-editor-di-fedora-25/
</span><span> 62. https://nalakawula.github.io/2017/05/20/flash-boot-android-menggunakan-fastboot/
</span><span> 63. https://nalakawula.github.io/2017/05/20/bongkar-boot.img-android-di-fedora-25/
</span><span> 64. https://nalakawula.github.io/2017/05/20/disable-tombol-kapasitip-hp-android-rom-cm13-google-seed/
</span><span> 65. https://nalakawula.github.io/2017/05/18/fedora-ala-ala-winten/
</span><span> 66. https://nalakawula.github.io/2017/05/17/membeli-nokia-150/
</span><span> 67. https://nalakawula.github.io/2017/05/16/menjaga-versi-kernel-tertentu-agar-tidak-terhapus-ketika-update-Fedora/
</span><span> 68. https://nalakawula.github.io/2017/05/09/tes-travis-ci/
</span><span> 69. https://nalakawula.github.io/2017/05/07/mencoba-oh-my-zsh/
</span><span> 70. https://nalakawula.github.io/2017/05/07/mencoba-zsh-di-fedora-25/
</span><span> 71. https://nalakawula.github.io/2017/04/27/memperbaiki-touchpad-error-di-fedora/
</span><span> 72. https://nalakawula.github.io/2017/04/25/menambah-tombol-navigasi-next-archive-previous-di-jekyll-bagian-II/
</span><span> 73. https://nalakawula.github.io/2017/04/18/menambah-tombol-navigasi-next-archive-previous-di-jekyll/
</span><span> 74. https://nalakawula.github.io/2017/04/17/memperbaiki-tampilan-emoji-di-gh-page/
</span><span> 75. https://nalakawula.github.io/2017/04/17/menambah-emoji-di-gh-page/
</span><span> 76. https://nalakawula.github.io/2017/04/16/menjalankan-tg-cli-di-raspberry-pi-3/
</span><span> 77. https://nalakawula.github.io/2017/04/14/raspberry-pi-3-headless/
</span><span> 78. https://nalakawula.github.io/2017/04/14/Meet-my-Pi-3/
</span><span>
</span><span> Hidden links:
</span><span> 80. https://nalakawula.github.io/
</span><span>
</span></code></pre>
Menjalankan Aplikasi Android di Sailfish OS
2018-09-29T12:25:51+07:00
2018-09-29T12:25:51+07:00
Unknown
https://www.sumarsono.com/menjalankan-aplikasi-android-di-sailfish-os/
<p>Sistem operasi tanpa aplikasi, sungguh laksana piring tanpa nasi. Begitu juga dengan sailfish OS. Kesan pertama memakai sailfish OS "WAW", gegas, gesture nikmat, konsisten, UI/UX yang mengesankan. Saya tidak sedang melebih-lebihkan, memang begitu yang saya rasakan. Dan yang paling mencengangkan adalah systemd yang dipakai. Cool.</p>
<p>Sayang-seribu sayang, dukungan aplikasi di sailfish OS benar-benar minim. Maklum, sistem operasi minoritas. Siapa sih developer yang mau bikin aplikasi tanpa pangsa pasar yang jelas? Wasting time. Hal tersebut yang kemudian mengilhami developer untuk membenamkan dukungan android ke sailfish OS, melalui <strong>aliendalvik</strong>. Penasaran? sama. Sayangnya, kita mesti membeli lisensi untuk hal tersebut <em>sad emoticon</em>.</p>
<p>Hampir putus asa, tapi ada kabar bahwa ada beberapa individu yang berhasil menjalankan aliendalvik di sailfish port. Ada harapan, setelah mengarungi dalamnya forum talk maemo, akhirnya saya bisa run aliendalvik di sailfish. Berikut ini langkah-langkah yang saya tempuh:</p>
<ol>
<li>Tentu saja memasang sailfish OS</li>
<li>Dump paket aliendalvik dan dependensinya dari official device, saya dump dari xperia X yang sudah terpasang aliendalik (lebih tepatnya, minta ke pemilik device ini).</li>
<li>SSH ke device sailfish kita</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>ssh nemo@192.168.2.15
</span></code></pre>
<ol start="4">
<li>Masuk ke mode root</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>devel-su
</span></code></pre>
<ol start="5">
<li>Masuk ke direktori hasil dump aliendalvik, nstall paket secara serentak, pernah coba satu-satu error.</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>zypper in *.rpm
</span></code></pre>
<ol start="6">
<li>sesuaikan isi <code>/opt/alien/system/script/</code> dengan device kita.</li>
<li>rename <code>/etc/media_platform.xml</code></li>
<li>run service aliendalvik <code>systemctl start aliendalvik</code></li>
</ol>
<p>Kalau sukses, bisa install apk. Saya telah coba install whatsapp dan tekegram X, fdroid, dan yalp. Semua berjalan lancar.</p>
<script async src="https://telegram.org/js/telegram-widget.js?4" data-telegram-post="unomindgithubio/5" data-width="100%" data-userpic="false"></script>
<p>Log aliendalvik yang berhasil run: <a href="https://del.dog/logad-1.diff">https://del.dog/logad-1.diff</a></p>
Sailfish OS untuk Mido
2018-09-27T15:33:00+07:00
2018-09-27T15:33:00+07:00
Unknown
https://www.sumarsono.com/sailfish-os-untuk-mido/
<p>Awalnya ingin porting Sailfish OS untuk Redmi Note 4 (Mido), akan tetapi saya urungkan karena di XDA sudah ada yang melakukan hal yang sama. Dia juga aktif di forum sailfish porter, bisa disebut dia kontribusi banyak. Jadi ya why i must reinvent the wheel. Terimakasih untuk kerja kerasnya, sehingga saya bisa menikmati sailfish os tanpa harus mengorbankan banyak hal.</p>
<p>Untuk menikmati sailfish di Mido, kita membutuhkan:</p>
<ul>
<li>TWRP 3.1.1.0</li>
<li>Firmware/ROM CM14.1 untuk Mido</li>
<li>Firmware sailfish OS hasil build Adam Piggz</li>
</ul>
<p>Dalam hal ini, saya berangkat dari Lineageos 15.1 (Oreo), jadi ya sudah punya TWRP, hanya saja TWRP terbaru tidak didukung oleh installer script dari CM14.1 dan sailfish OS.</p>
<ol>
<li>Reboot ke TWRP</li>
<li>Flash image TWRP 3.1* ke partisi Recovery</li>
<li>Reboot recovery</li>
<li>Format data</li>
<li>Install Cm14.1</li>
<li>Install sailfish OS</li>
<li>Reboot</li>
</ol>
<p>Selamat menikmati sailfish OS di Mido.</p>
<script async src="https://telegram.org/js/telegram-widget.js?4" data-telegram-post="unomindgithubio/4" data-width="100%" data-userpic="false"></script>
<p>Klien telegram untuk sailfish OS:</p>
<script async src="https://telegram.org/js/telegram-widget.js?4" data-telegram-post="unomindgithubio/3" data-width="100%" data-userpic="false"></script>
Shelter - Isolate your Big brother App - Multiple Accounts
2018-09-17T11:24:48+07:00
2018-09-17T11:24:48+07:00
Unknown
https://www.sumarsono.com/shelter-isolate-your-big-brother-app-multiple-accounts/
<p>Hari ini secara tidak sengaja saya menemukan sebuah aplikasi yang menarik. Berawal dari ketika saya mengunjungi <a href="https://www.reddit.com/r/LineageOS/">/r/LineageOS/</a>. Disana ada yang merekomendasikan sebuah aplikasi, yakni <a href="https://f-droid.org/packages/net.typeblog.shelter/">Shelter</a>. Apa itu Shelter? berikut ini saya kutip dari deskripsi di repo f-droid:</p>
<blockquote>
<p>Shelter is a Free and Open-Source (FOSS) app that leverages the “Work Profile” feature of Android to provide an isolated space that you can install or clone apps into.</p>
</blockquote>
<blockquote>
<p>Shelter comes with absolutely no advertisement / statistics / tracking SDKs bundled with it. All source code is available in this public Git repository and the sources are licensed under WTFPL.</p>
</blockquote>
<p>Menarik bukan? Oh iya, bagi pengguna fitur <em>app clone</em> khas Miui, pasti akan suka. Saya sudah mencoba Shelter di HP dengan sistem operasi dari LineageOS. Belum ada sehari sih, tapi so far so good.</p>
<p><img src="/assets/images/Shelter1.webp" alt="Shelter" />
<img src="/assets/images/Shelter2.webp" alt="Shelter" />
<img src="/assets/images/Shelter3.webp" alt="Shelter" /></p>
Setelah Install Windows 10?
2018-07-02T09:32:26+07:00
2018-07-02T09:32:26+07:00
Unknown
https://www.sumarsono.com/setelah-install-windows-10/
<p>WSL tentunya, sejak awal digaungkan, saya memang penasaran dengan Windows Subsystem for Linux. Setelah selesai upgrade dari win7 ke win10, langsung login menggunakan akun yang terdaftar di Microsoft, membuka Windows store, dan langsung cari <code>linux</code>.</p>
<p><img src="/assets/images/linux-wsl.webp" alt="Linux di Ms. Store" /></p>
<p>Banyak sekali opsinya, tapi saya mau jajal ubuntu saja, alasannya ya karena anuan ubuntu ini ada kedekatan dengan anuan Ms.
<img src="/assets/images/ubuntu-wsl.webp" alt="Ubuntu di Ms. Store" /></p>
<p>Langsung install, dan jangan lupa aktifkan fitur Windows Subsystem for Linux. So far so good, cuma lokasi <code>/</code> yang agak nganu, coba saja nanti juga tahu sendiri :laugh:</p>
<p><a href="https://pegelinux.id/comment/381">Komentar dimari</a></p>
Free Upgrade Windows 7 Pro OEM ke Windows 10
2018-07-01T13:52:22+07:00
2018-07-01T13:52:22+07:00
Unknown
https://www.sumarsono.com/free-upgrade-windows-7-pro-oem-ke-windows-10/
<blockquote>
<p>"Sesungguhnya, Windows adalah hidayah jika kamu mengetahui" - Teman</p>
</blockquote>
<p>Ms. Windows merupakan sistem operasi sejuta umat, tidak diragukan lagi. Bahkan, Microsoft menawarkan <em>upgrade</em> gratis ke Windows 10 bagi konsumen yang mempunyai lisensi Windows. Sebenarnya sudah sejak lama, tapi kala itu saya masih menikmati Windows 7, selain alasan <em>habbit</em> juga karena ada aplikasi dari vendor PLC yang tidak berjalan sebagaimana mestinya jikan dijalankan di sistem operasi yang lebih tinggi dari Windows 7.</p>
<p>Namun sekarang, karena ada laptop pengganti, saya jadi ingin merasakan upgrade secara daring yang ditawarkan oleh Microsoft. Setelah menggali informasi, ternyata Microsoft telah mengumumkan bahwa layanan tersebut <a href="https://support.microsoft.com/en-us/help/12435/windows-10-upgrade-faq">sudah dihentikan</a>. Sayang sekali, tapi ada beberapa artikel yang menceritakan bahwa masih ada yang berhasil upgrade walau melebihi tenggat waktu dari Microsoft. <em>For science</em>, apa salahnya mencoba. Kebetulan hari ini saya memiliki waktu luang <em>to do something</em>. </p>
<blockquote>
<p>Spoiler, <em>upgrade</em> <strong>BERHASIL</strong>. Windows 10 activated dan bisa ditautkan ke surel.</p>
</blockquote>
<p><img src="/assets/images/upgrade-5.webp" alt="Registry ICS" /></p>
<p>Bagi yang ingin tahu apa saja langkah yang sudah saya tempuh, berikut ini gambarannya:</p>
<ol>
<li>Siapkan koneksi yang bagus, dan listrik tentunya karena prosesnya memakan waktu yang cukup lama. Bisa ditinggal <del>boker</del></li>
<li>Download Windows Media Creator dari situs <a href="https://www.microsoft.com/en-us/software-download/windows10">Microsoft</a>.</li>
<li>Jalankan Windows Media Creator dan ikuti instruksinya.</li>
<li>Prosesnya lama dan akan terjadi beberapa kali restart, <em>so be patient</em>.</li>
</ol>
<p>Komentar? <a href="https://pegelinux.id/comment/378">dimari</a></p>
Move on, Life Must Go On
2018-06-30T20:18:37+07:00
2018-06-30T20:18:37+07:00
Unknown
https://www.sumarsono.com/move-on-life-must-go-on/
<p>Saya memutuskan untuk mengubah beberapa hal. Beberapa diantaranya adalah sebagai berikut:</p>
<ol>
<li>
<p>Mengubah username github
github.com/sumarouno terasa sulit diucap, itu sebabnya saya ubah ke github.com/unomind. Berdampak pada gh-pages juga, semula sumarouno.github.io menjadi nalakawula.github.io</p>
</li>
<li>
<p>Meninggalkan <code>disquss</code>
Apakah karena jelek? Tidak. Disquss sangat mumpuni sebagai <em>commenting system</em>. Hanya saja saya merasa tidak cocok. Terlebih lagi telah lahir agregator <a href="https://pegelinux.id">pegelinux</a>. Silakan berkomentar disana.</p>
</li>
<li>
<p>Perubahan lain
Saya rasa yang ini menjadi <em>part of my life</em> yang belum bisa saya tulis.</p>
</li>
</ol>
<p>Komentar? <a href="https://pegelinux.id/comment/343">dimari</a></p>
Selamat Idulfitri
2018-06-29T23:32:19+07:00
2018-06-29T23:32:19+07:00
Unknown
https://www.sumarsono.com/selamat-idulfitri/
<p>Terlambat, akan tetapi tak mengapa. Saya mengucapkan selamat Idulfitri 1439H. Mohon maaf lahir dan batin.
:smile:
Terima kasih</p>
Mencicipi MIUI Global Dev
2018-03-27T21:02:36+07:00
2018-03-27T21:02:36+07:00
Unknown
https://www.sumarsono.com/mencicipi-miui-global-dev/
<p>This is, sad story....</p>
<p>Hari ini, rasa penasaran terhadap MIUI Global Dev muncul dalam kalutnya hati. Rasa itu hanya bisa diobati dengan mencicipi. Terunduhlah file sebesar 1,5GB ke dalam penyimpanan HP.</p>
<ol>
<li>Reboot ke TWRP.</li>
<li>Wipe <code>system</code>, <code>data</code>, <code>cache</code> dan <code>dalvic cache</code>.</li>
<li>Flash zip file miui global dev, eh auto reboot (dalam benak, wah shit happen jangan2).</li>
<li>Saya tunggu beberapa menit, kok tidak sampai setup wizard miui 9, muncul getar 3x.</li>
<li>Reboot paksa, dan jreng masuk ke setup wizard....eh....error gagal pada saat proses enkripsi dan ponsel harus di format karena data sudah tidak dapat di akses....OMG...really shit.</li>
<li>Reboot recovery, wtf, twrp ketimpa recovery bawaan siaomeme.</li>
<li>Akses data sudah tidak bisa.</li>
<li>Terpakas format</li>
<li>My photos, and other files, were gone, so sad....</li>
</ol>
Mengganti IP standar ICS Windows 7
2018-03-19T08:41:44+07:00
2018-03-19T08:41:44+07:00
Unknown
https://www.sumarsono.com/mengganti-ip-standar-ics-windows-7/
<p>Windows 7 memiliki fitur <em>Internet Connection Sharing (ICS)</em>, yaitu sebuah fitur yang memungkinkan kita untuk membagi koneksi internet dari satu adapter ke adapter lain. Bukan fitur yang wah, sih. Di distribusi linux rasanya fitur tersebut lebih <em>mantab soul</em>. Alhail GNU/Linux.</p>
<p>Secara <em>default</em> IP hasil konfigurasi ICS adalah 192.168.137.x, bagaimana caranya agar ip default-nya bukan ip tsb? Berikut ini caranya:</p>
<ol>
<li>Masuk Registry Editor</li>
<li>Pada panel kiri, cari:</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\SharedAccess\Parameters
</span></code></pre>
<ol start="3">
<li>Setelah itu, pada bagian panel kanan akan akan ada <strong>Scope Address</strong> dan <strong>StandAloneDHCPAddress</strong>, ubah nilai dari dua paramater tsb dengan ip address yg kita kehendaki.</li>
<li>Reboot</li>
<li>Profit
<img src="/assets/images/ics1.webp" alt="Registry ICS" /></li>
</ol>
<p><img src="/assets/images/ics2.webp" alt="Registry ICS" /></p>
<p>Sudah sih, hanya seperti itu.</p>
Kamera bokeh ala-ala Google Camera
2018-02-02T15:01:00+07:00
2018-02-02T15:01:00+07:00
Unknown
https://www.sumarsono.com/kamera-bokeh-ala-ala-google-camera/
<p>Mmmm, pernah dengar kamera bokeh? Pernah dengar istilah dual cam di smartphone mahal? Pasti pernah lah ya, nak milenial, nak gaul, nak kekinian.</p>
<p>Untuk hasil jepretan kamera yang bokeh, tidak harus dual cam sih, bisa kok bokeh ala-ala software. Pakai fitur potrait google camera misalnya. Beruntungnya, google camera sudah di port untuk device lain oleh orang-orang pintar dan baik hati di luar sana. Linknya? kemari aja <a href="https://www.celsoazevedo.com/files/android/google-camera/">https://www.celsoazevedo.com/files/android/google-camera/</a></p>
<p>Minta sample hasil jepret? tidak ah, wajah saya terlalu tampan dan berani.</p>
<p>Salam bokeh.
Terimakasih</p>
Client to Server (C2S) Port Forwarding Menggunakan BitVise SSH Client
2018-01-29T09:32:00+07:00
2018-01-29T09:32:00+07:00
Unknown
https://www.sumarsono.com/client-to-server-c2s-port-forwarding-menggunakan-bitvise-ssh-client/
<p>Sebenarnya, ini merupakan hal yang sederhana, alkisah saya punya server kecil. Di server tersebut, ada sebuah <em>anuan</em> yang menggunakan port <em>ABCD</em> dan <em>EFGH</em>. Saya ingin akses anuan tersebut dapat diakses dari komputer lain menggunakan <code>ssh tunnel</code>. Kalau di linux mah <em>gampil</em> , tinggal:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>ssh "remote-IP" -p "remote-ssh-port" -L BLABLA:localhost:ABCD -L BLILI:localhost:EFGH -l "ssh-user"
</span></code></pre>
<p>BLABLA = port lokal kita.
BLIBLI = port lokal kita.
Jadi ketika kita akses localhost:BLABLA akan lari ke remote-IP:ABCD. Ketika akses localhost:BLIBLI akan lari ke remote-IP:EFGH.</p>
<p>Kalau di Windows? Saya bingung bagaimana caranya, akhirnya browsing dan ketemu <a href="https://www.bitvise.com/port-forwarding">BitVise SSH Client</a>.</p>
<p>Caranya seperti terlihat di gambar contoh, berikut ini:
<img src="/assets/images/c2s.webp" alt="C2S" /></p>
<p>Selebihnya tidak perlu saya jelaskan, karena BitVise ini cukup <em>user friendly</em>.</p>
<p>Terimakasih</p>
Setup Vagrant di Windows 7 Pro x64
2018-01-18T13:37:00+07:00
2018-01-18T13:37:00+07:00
Unknown
https://www.sumarsono.com/setup-vagrant-di-windows-7-pro-x64/
<p>Di Windows, hampir semua yang terkait dengan pemasangan aplikasi sangatlah mudah, next next next finish. Seperti itu kira-kira gambaran yang ada dalam otak saya dan saya tuangkan dalam tulisan tak mutu ini. Beberapa hari yang lalu, saya mencoba setup vagrant di Windows 7. Instalasi sungguh tidak ada kendala, lancar jaya. Tetapi, kendala justru muncul ketika <code>vagrant up</code>, bengong, tidak ada reaksi, ditunggu sampai lumutan juga tidak membuahkan hasil, layaknya menunggu jawaban dari doi (bukan pengalaman saya).</p>
<p>Akhirnya saya jalankan mode debug, dan tanya ke mbah <em>you know him</em>. Ternyata yang jadi masalah adalah powershell, harus diupdate ke versi 3. Setelah install <strong>WMF</strong>, akhirnya powershell naik versi dan <code>vagrant up</code> berjalan mulus, semulus singkong yang baru dikupas.</p>
<p>Itu saja tulisan artikel ini, sangat gaje dan mungkin nirfaedah.</p>
Aktivasi Windows 7 Pro OEM Melalui Jalur Telepon
2018-01-18T08:48:30+07:00
2018-01-18T08:48:30+07:00
Unknown
https://www.sumarsono.com/aktivasi-windows-7-pro-oem-melalui-jalur-telepon/
<p>I have a laptop that came with Windows 7 Pro, preinstalled. Laptop ini harddisknya sudah saya partisi ulang dan saya pasang sistem operasi GNU/Linux, mulai dari Fedora, Manjaro, Arch, dan terakhir Debian 9 (semoga pembuatnya tenang di alam sana,he has given the great OS to the world). Dan sekarang, saya ganti HDD tsb dengan SSD, dan saya berniat untuk menggunakan OS bawaanya yaitu Windows 7 Pro.</p>
<p>Sejauh proses penggantian hingga aktivasi, tidak ada kendala sama sekali. So, saya tidak akan menulis secara rinci karena hal itu hanya akan <em>menggarami air laut</em>. Kenapa saya tulis artikel begini? katanya menggarami air laut. Jawabannya, karena akan menyenangkan ketika saya tua nanti dan saya membaca tulisan yang saya tulis waktu muda.</p>
<p>Ringkasnya, yang saya lakukan adalah sebagai berikut:</p>
<ol>
<li>Melepas HDD.</li>
<li>Memasang SSD.</li>
<li>Mengambil gambar lisensi Windows yang tertempel di belakang laptop.</li>
<li>Membuat bootable USB Windows 7 Pro.</li>
<li>Install Windows.</li>
<li>Aktivasi Windows dengan melakukan panggilan ke <strong>001 803 65 7668</strong> (bebas pulsa).</li>
<li>Selesai.</li>
</ol>
<p>Semoga bermanfaat.</p>
Autocutoff Charging Menggunakan Arduino
2017-12-17T08:44:09+07:00
2017-12-17T08:44:09+07:00
Unknown
https://www.sumarsono.com/autocutoff-charging-menggunakan-arduino/
<p>HP menjadi sebuah kebutuhan primer, saya tidak menyangkalnya. Hampir 24 jam setiap hari HP selalu ada di dekat saya. Bicara soal HP, tidak lepas dari baterai dan charging. Biasanya HP saya, biasa hidup dari jam 3 pagi, sampai jam 12 malam. Waktu antara 00:00 - 03:00, saya gunakan untuk charging, karena itu pas dengan jam istirahat. Namun demikian, sering terjadi hal-hal luar biasa, misalnya saya tidur jam 20:00 atau jam 21:00 karena lelah setelah aktivitas siang hari. Pada saat saya tidur, HP harus dicharge, karena saya butuh untuk esok pagi. Bayangkan, jika saya tidur jam 21:00 dan bangun jam 03:00, HP saya charge selama 6 jam. Lama-lama bisa jebol baterainya. Kalau jebol bisa repot, jama sekarang HP model unibody, susah gantinya.</p>
<p>Berangkat dari masalah tsb, saya berinisiatif untuk membuat timer autocutoff charging. Wah keren, beli jadi ada banyak sepertinya. Mmm, kalau beli alat yang sudah jadi, berasa kurang <em>geek</em>. Kebetulan saya punya komponen-komponen nganggur bekas mainan jaman dulu. Dimanfaatkan saja.</p>
<p>Secara garis besar, saya butuh:</p>
<ol>
<li>Arduino sebagai kontroler, kebetulan saya punya beberapa Arduino Nano nganggur.</li>
<li>RTC DS3231, sekalian aja bikin jam digital.</li>
<li>Adaptor 9V 2A, untuk catu daya. 1A juga tidak masalah, kebetulan saja punyanya itu.</li>
<li>IC regulator 7805, untuk regulasi tengangan ke uC, LCD, Relay, RTC.</li>
<li>Komponen penunjang seperti elco, dc barrel jack, pcb bolong, kabel, push button, dll.</li>
<li>LCD 1602, saya punya yang sudah saya tambah I2C, lumayan untuk menghemat pin uC.</li>
<li>Modul relay.</li>
<li>Stop kontak, yang akan dipotong jalur listriknya.</li>
</ol>
<p>Apa yang saya pikirkan untuk dibuat:</p>
<ol>
<li>LCD menampilkan hari, tanggal, bulan, tahun, jam, menit, detik, timer.</li>
<li>Ada sistem menu sederhana untuk pengaturan poin nomer 1.</li>
<li>Fungsi timer ini yang ingin saya pakai untuk cutoff charging. Misalnya HP akan penuh setelah 2 jam 30 menit, tinggal masuk menu, set timer dari jam sekarang ditambah 2 jam 30 menit.</li>
</ol>
<p>Prototipe jelek ini sudah jadi baik hardware maupun programnya, dan sudah saya coba. Pembahasan lebih lanjut, nantikan artikel berikutnya.</p>
Resize Aplikasi Microsoft Office 2010 di Wine
2017-12-01T20:53:10+07:00
2017-12-01T20:53:10+07:00
Unknown
https://www.sumarsono.com/resize-aplikasi-microsoft-office-2010-di-wine/
<p>Microsoft Office 2010 yang saya pasang dengan bantuan Wine, <em>so far so good</em>. Fungsi-fungsi yang saya butuhkan berjalan sebagaimana mestinya. Tapi, ada sesuatu yang aneh walaupun tidak mengganggu pekerjaan, yaitu Aplikasi MSO tidak bisa di resize menggunakan tombol resize di <em>tittle bar</em>. Misal saya buka Ms Word, ketika saya klik resize maka akan mengecil, ketika saya klik rezie sekali lagi, tidak terjadi apa-apa, seharusnya jadi maximize.</p>
<p>Ternyata, hal tersebut berkaitan dengan window manager dari DE. Berhubung saat ini saya menggunakan KDE, maka solusinya adalah sebagai berikut:</p>
<ol>
<li>Buka <strong>System Settings</strong></li>
<li>Dari <strong>System Setttings</strong> buka <strong>Window Managements</strong></li>
<li>Setelah <strong>Window Management</strong> terbuka, Klik _<em>Window Rules</em> > <strong>New..</strong></li>
<li>Pada kolom isian <em>Description</em>, isilah nama untuk rule yang akan dibuat</li>
<li><strong>Window Class (Application)</strong>: Pilih regular expression dan isi dengan <code>.*\b(winword.exe|excel.exe|powerpnt.exe)\b.*</code></li>
<li>Klik tab <strong>Size & Position</strong></li>
<li>Centang <strong>Full Screen</strong>, Opsi <strong>Force</strong>, <strong>No</strong></li>
<li>Centang <strong>Ignore Requested Geometry</strong>, Opsi <strong>Force</strong>, <strong>Yes</strong></li>
<li>Profit</li>
</ol>
<p>Sumber: <a href="https://www.codeweavers.com/compatibility/crossover/forum/microsoft-office-2010?msg=157908">https://www.codeweavers.com/compatibility/crossover/forum/microsoft-office-2010?msg=157908</a></p>
Menautkan Kalender Google ke KOrganizer KDE
2017-12-01T06:57:27+07:00
2017-12-01T06:57:27+07:00
Unknown
https://www.sumarsono.com/menautkan-kalender-google-ke-korganizer-kde/
<p>Untuk menautkan kalender Google ke KOrganizer KDE, sangatlah mudah. Caranya:</p>
<ol>
<li>Buka KOrganizer</li>
<li>Klik <strong>Settings</strong> > <strong>Configure KOrganizer...</strong></li>
<li>Klik <strong>General</strong> > <strong>Calendars</strong></li>
<li>Klik tombol <strong>Add...</strong> kemudian cari dengan kata kunci <em>Google</em></li>
<li>Ikuti wizard dari Google</li>
<li>Profit</li>
</ol>
<blockquote>
<p>Google is your friend, jangan berpaling darinya.</p>
</blockquote>
Instalasi Microsoft Office 2010 di Debian 9
2017-11-28T10:39:18+07:00
2017-11-28T10:39:18+07:00
Unknown
https://www.sumarsono.com/instalasi-microsoft-office-2010-di-debian-9/
<p>Debian 9 hadir dengan Office Suite bernama LibreOffice, namun demikian tak dapat kita pungkiri bahwa dalam dunia Office Suite, Microsoft Office adalah rajanya. Kalau untuk keperluan pribadi, mungkin LibreOffice sudah cukup untuk memenuhi kebutuhan. Tapi akan menjadi lain cerita kalau menyangkut urusan pekerjaan, menyangkut khalayak banyak, dokumen yang kita olah harus dapat dibuka oleh orang lain. Sayangnya kompatibilitas LO terhadap MSO dan sebaliknya, belum cukup bagus. Oleh sebab itu, dalam artikel ini akan dibahas cara instalasi MSO 2010 di sistem operasi Debian 9 dengan bantuan program PlayOnLinux.</p>
<p>PlayOnLinux merupakan program yang sangat berguna untuk memudahkan instalasi aplikasi Windows di lingkungan GNU/Linux. Ia merupakan frontend untuk Wine.</p>
<p>Pada artikel ini, akan saya paparkan bagaimana cara instalasi MSO 2010 di Debian 9 menggunakan PlayOnLinux. Berikut ini adalah beberapa hal yang kita butuhkan:</p>
<ol>
<li>PlayOnLinux installed.</li>
<li>Microsoft Office 2010 (32-Bit Edition) DVD atau ISO image file.</li>
<li>Koneksi internet yang bagus.</li>
</ol>
<p>Selanjutanya, masuk ke tahap instalasi PlayOnLinux:</p>
<ol>
<li>Update database repo Debian 9</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo apt-get update
</span></code></pre>
<ol start="2">
<li>Install PlayOnLinux</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo apt-get install playonlinux -y
</span></code></pre>
<ol start="3">
<li>Install Winbind</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>Sudo apt-get install winbind
</span></code></pre>
<p>Setelah itu, kita install Microsoft Office 2010:</p>
<ol>
<li>Buka PlayOnLinux</li>
<li>Klik tombol <strong>Install</strong> di toolbar atas, atau klik <strong>Install a program</strong> di sidebar Action, maka PlayOnLinux akan update database, tunggu hingga selesai.</li>
<li>Klik Tab <strong>Office</strong> kemudian pilih <strong>Microsoft Office 2010</strong> kemudian klik <strong>Install</strong>.</li>
<li>Klik <strong>Ok</strong> pada dialog warning, 3x Next, pilih <strong>Use DVD-ROM(s)</strong>, pilih <strong>Other</strong>, klik Next.</li>
<li>Arahkan ke setup.exe installer MSO 2010 dan klik Next.</li>
<li>Ikuti wizard MSO 2010.</li>
<li>Selesai? Klik finish.</li>
<li>Profit.</li>
</ol>
Virtualbox - Mengatasi Nerwork Adapter 2 tidak mendapatkan IP Address dari DHCP Server
2017-11-24T18:50:04+07:00
2017-11-24T18:50:04+07:00
Unknown
https://www.sumarsono.com/virtualbox-mengatasi-nerwork-adapter-2-tidak-mendapatkan-ip-address-dari-dhcp-server/
<p>Hari ini, saya mainan virtualbox dengan setup sebagai berikut:</p>
<ul>
<li>Sistem operasi: Ubuntu 16.04</li>
<li>Network Adapter 1: NAT</li>
<li>Network Adapter 2: Host-Only adapter</li>
<li>Host only adapter sudah diset sebagai DHCP Server</li>
</ul>
<h2 id="masalah">Masalah</h2>
<p>Setelah selesai Intsall sistem operasi, ternyata adapter 2 tidak mendapatkan IP Address.</p>
<h2 id="solusi">Solusi</h2>
<ol>
<li>Cek apakah network adapater 2 terdeteksi oleh sistem,</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>ip link
</span></code></pre>
<p>Catat outputnya, misal adapter 1 terdeteksi sebagai ens0p3 dan adapter 2 tereteksi sebagai ens0p8.
2. Edit <code>/etc/network/interfaces</code> dan isi dengan:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>auto ens0p3
</span><span>iface ens0p3 inet dhcp
</span><span>auto ens0p8
</span><span>iface ens0p8 inet dhcp
</span></code></pre>
<ol start="3">
<li>Restart network</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo systemctl restart networking
</span></code></pre>
<ol start="4">
<li>Profit</li>
</ol>
KDE yang Sekarang bukan KDE yang Dulu
2017-11-10T18:30:47+07:00
2017-11-10T18:30:47+07:00
Unknown
https://www.sumarsono.com/kde-yang-sekarang-bukan-kde-yang-dulu/
<p><img src="/assets/images/ss-plasma-desktop2.webp" alt="KDE-PLASMA" />
Gambar 1: Monitoring resource usage KDE Plasma
{: style="color:gray; font-size: 80%; text-align: center;"}</p>
<p>Setelah sekian lama menjadi pengguna GNOME, akhirnya saya coba berpaling dan menjajal KDE. Wow, saya tercengang KDE yang sekarang beda sekali dengan KDE yang dulu. Lihat skrinsut di atas, cakep menurut saya. Terlebih konsumsi RAM-nya lebih kecil dibandingkan dengan GNOME, imo. Meskipun ada yang bilang RAM itu dibeli untuk dipakai, bukan untuk dianggurin. Namun demikian, Saya masih belum nyaman mengikuti workflow KDE. Saya masih nyaman dengan workflow GNOME.</p>
Telegram Desktop Multiple Instances
2017-11-05T11:05:10+07:00
2017-11-05T11:05:10+07:00
Unknown
https://www.sumarsono.com/telegram-desktop-multiple-instances/
<p>Punya dua nomor HP?
Setiap nomor dibuatkan akun telegram?
Ingin login dua-duanya dalam satu komputer?</p>
<p>Jika jawaban pertanyaan diatas adalah iya, caranya mudah.
bash
Telegram -many -workdir "/path/nomor1/"</p>
<p>Telegram -many -workdir "/path/nomor2/"</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>
</span><span>Sumber: [https://github.com/telegramdesktop/tdesktop/issues/533](https://github.com/telegramdesktop/tdesktop/issues/533)</span></code></pre>
Mudah Konversi Skema GPT ke MBR
2017-10-29T17:42:25+07:00
2017-10-29T17:42:25+07:00
Unknown
https://www.sumarsono.com/mudah-konversi-skema-gpt-ke-mbr/
<p>Apa itu GPT?
Apa itu MBR?
Silakan <em>surfing</em> saja untuk mencari tahu tentang GPT dan MBR.</p>
<h3 id="kronologi">Kronologi</h3>
<p>Si A membeli HDD 500GB seken, untuk mengganti HDD laptopnya yang rusak. Setelah dipasang, mau diinstall Windows 7. Ternyata ditengah jalan muncul error yang intinya Windows tidak dapat diinstall di HDD tersebut. Usut punya usut, pemilik sebelumnya memformat HDD tsb. dengan skema GPT. Kalau begitu, harus di konversi ke MBR.</p>
<h3 id="kendala">Kendala</h3>
<ol>
<li>Tidak ada komputer lain</li>
<li>Tidak punya bootable OS selain installer Windows 7</li>
</ol>
<h3 id="solusi">Solusi</h3>
<ol>
<li>Di Wizard installer window 7, tekan <kbd>shift</kbd> + <kbd>F10</kbd></li>
<li>Jalankan diskpart</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>diskpart
</span></code></pre>
<ol start="3">
<li>List disk</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>list disk
</span></code></pre>
<ol start="4">
<li>Pilih disk yang mau dikonversi</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>select disk 0
</span></code></pre>
<ol start="5">
<li>Clean untuk menghapus semua partisi dan dari disk yang terpilih</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>clean
</span></code></pre>
<ol start="6">
<li>Konversi ke MBR</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>convert mbr
</span></code></pre>
<ol start="7">
<li>Reboot</li>
<li>Profit</li>
</ol>
<p>Sudah gitu aja</p>
Jekyll Trik untuk Image Caption
2017-10-27T20:51:00+07:00
2017-10-27T20:51:00+07:00
Unknown
https://www.sumarsono.com/jekyll-trik-untuk-image-caption/
<p>Hari ini, saya ingin menaruh gambar dalam artikel dengan tampilan seperti ini:
<img src="/assets/images/image-caption.webp" alt="gambar+caption" /></p>
<p>Saya, tidak tahu cara yang "benar" dalam jekyll, sehingga saya membuatnya seperti ini:</p>
<pre data-lang="markdown" style="background-color:#fcf0ca;color:#282828aa;" class="language-markdown "><code class="language-markdown" data-lang="markdown"><span>![utilman.webp](/assets/images/utilman.webp)
</span><span>Gambar 1: utilman.exe (https://www.online-tech-tips.com/)
</span><span>{: style="color:gray; font-size: 80%; text-align: center;"}
</span></code></pre>
<p>Profit, hasilnya dapat dilihat [disini]({% post_url 2017-10-24-mudah-bypass-password-windows-10 %})</p>
<p>Referensi: <a href="https://stackoverflow.com/questions/28294959/jekyll-kramdown-how-to-center-text">https://stackoverflow.com/questions/28294959/jekyll-kramdown-how-to-center-text</a></p>
Mudah Bypass Password Windows 10
2017-10-24T21:04:05+07:00
2017-10-24T21:04:05+07:00
Unknown
https://www.sumarsono.com/mudah-bypass-password-windows-10/
<p><img src="/assets/images/utilman.webp" alt="utilman.webp" />
Gambar 1: utilman.exe (https://www.online-tech-tips.com/)
{: style="color:gray; font-size: 80%; text-align: center;"}</p>
<p>Mungkin, kelak akan kita akan mengalami keadaan tidak bisa login ke desktop Windows 10 karena lupa password. Akan tetapi keadaan memaksa kita untuk dapat masuk. Untuk bypass password login Windows 10, ada banyak cara. Apa yang saya tulis disini hanyalah salah satunya. Tentunya sudah saya lakukan, karena tulisan ini saya maksudkan untuk "jika saya lupa". Solusi yang saya tulis disini yaitu memanfaatkan <code>utilman.exe</code> yang ada di login screen Windows 10.</p>
<h3 id="persiapan">Persiapan</h3>
<p>Kita harus memiliki:</p>
<ol>
<li>Image Windows Installer</li>
<li>Media untuk <code>boot</code> (Saya sarankan menggunakan Flashdisk)</li>
</ol>
<h3 id="eksekusi">Eksekusi</h3>
<p>Step by step-nya adalah sebagai berikut:</p>
<ol>
<li>Buat bootable media Windows.</li>
<li>Boot dari bootable media tadi.</li>
<li>Setelah berhasil boot dan masuk ke pemilihan <strong>regional and language</strong>, silakan tekan <kbd>SHIFT</kbd> + <kbd>F10</kbd> sehingga muncul jendela command prompt.</li>
<li>Backup file <code>utilman.exe</code>.
bash
move e:\Windows\System32\Utilman.exe e:\Windows\System32\Utilman.exe.bak</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>5. Copy `cmd.exe` menjadi `utilman.exe` dengan maksud agar ketika di login screen windows dan kita klik `Utility Manager` yang muncul adalah jendela `CMD`.
</span><span>bash
</span><span>copy e:\Windows\System32\cmd.exe e:\Windows\System32\Utilman.exe
</span></code></pre>
<p>Catatan: <code>e</code> adalah partisi system Windows, silakan disesuaikan.
6. Reboot dan boot dari HDD windows.
bash
wpeutil reboot</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>7. Setelah muncul login screen, klik `Utility Manager` dan jreng jreng muncul jendela CMD.
</span><span>8. Buat user baru dan jadikan administrator.
</span><span>bash
</span><span>net user <username> /add
</span><span>net localgroup administrators <username> /add
</span></code></pre>
<ol start="9">
<li>Tutup CMD, dan reboot.</li>
<li>Login ke akun yang tadi dibuat.</li>
<li>Profit.</li>
</ol>
<p>Nah dari akun baru yang kita buat, kita dapat mereset password akun yang lain.</p>
<p>Terimakasih</p>
Mengatasi Error import gobject Ketika Menjalankan hp-setup di Arch Linux
2017-10-17T09:50:58+07:00
2017-10-17T09:50:58+07:00
Unknown
https://www.sumarsono.com/mengatasi-error-import-gobject-ketika-menjalankan-hp-setup-di-arch-linux/
<p>Pagi ini, ketika saya mau setup printer merk HP muncul error seperi berikut ini:
bash
[sumarsono@mesin-arch ~]$ hp-setup </p>
<p>HP Linux Imaging and Printing System (ver. 3.17.9)
Printer/Fax Setup Utility ver. 9.0</p>
<p>Copyright (c) 2001-15 HP Development Company, LP
This software comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to distribute it
under certain conditions. See COPYING file for more details.</p>
<p>Traceback (most recent call last):
File "/usr/bin/hp-setup", line 313, in <module>
ui = import_module(ui_package + ".setupdialog")
File "/usr/lib/python3.6/importlib/<strong>init</strong>.py", line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 978, in _gcd_import
File "<frozen importlib._bootstrap>", line 961, in _find_and_load
File "<frozen importlib._bootstrap>", line 950, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 655, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 678, in exec_module
File "<frozen importlib._bootstrap>", line 205, in _call_with_frames_removed
File "/usr/share/hplip/ui5/setupdialog.py", line 31, in <module>
from base import device, utils, models, pkit
File "/usr/share/hplip/base/pkit.py", line 38, in <module>
from gi import _gobject as gobject
ImportError: cannot import name '_gobject'</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>
</span><span>### Solusi
</span><span>Sangat mudah, cukup install `python-gobject` sudah beres.
</span><span>
</span><span>Profit, happy printing.</span></code></pre>
Setup Raspberry Pi Super Headless
2017-10-01T18:50:58+07:00
2017-10-01T18:50:58+07:00
Unknown
https://www.sumarsono.com/setup-raspberry-pi-super-headless/
<p>Kok super headless?
Kasusnya begini, kita punya:</p>
<ol>
<li>Raspberry Pi 3</li>
<li>Kabel LAN</li>
<li>Flashdisk Sandisk 4GB</li>
<li>Adaptor 5V3A</li>
<li>Laptop</li>
<li>USB TTL</li>
</ol>
<p>Saya sebut super headless karena raspi akan saya setup tanpa DHCP server.</p>
<h3 id="langkah-langkahnya">Langkah-langkahnya</h3>
<ol>
<li>Download OS untuk raspberry pi, Raspbian Lite <a href="https://www.raspberrypi.org/downloads/raspbian/">DISINI</a>.</li>
<li>Restore image raspbian ke flashdisk, terserah mau pakai tool apa, <code>dd</code>, <code>gnome-disk</code>, <code>etcher</code>.</li>
<li>Setelah selesai, akan muncul partisi <code>boot</code> dari flashdisk, buka saja.</li>
<li>Enable UART raspi, Cari file <code>config.txt</code> kemudian tambahkan <code>enable_uart=1</code></li>
<li>Pasang flashdisk ke raspi</li>
<li>Hubungkan USB TTL ke raspi dan laptop</li>
</ol>
<ul>
<li><pre style="background-color:#fcf0ca;color:#282828aa;"><code><span> GND --- GND
</span></code></pre>
</li>
<li><pre style="background-color:#fcf0ca;color:#282828aa;"><code><span> RX --- TX
</span></code></pre>
</li>
<li><pre style="background-color:#fcf0ca;color:#282828aa;"><code><span> TX --- RX
</span></code></pre>
</li>
</ul>
<ol start="7">
<li>Di laptop pasang aplikasi buat UART, misalnya <code>screen</code>, <code>putty</code>.</li>
<li>Akses UART, <code>sudo screen /dev/ttyUSB0 115200</code></li>
<li>Hidupkan raspi, nanti muncul log boot kemudian muncul login prompt.</li>
<li>Profit</li>
</ol>
<p>Kalian pasti menyadari kalau saya tidak memakai microSD, perlu kalian ketahui bahwa raspi 3 bisa boot dari USB.</p>
Mencoba jekyll-admin
2017-09-30T11:00:00+07:00
2017-09-30T11:00:00+07:00
Unknown
https://www.sumarsono.com/mencoba-jekyll-admin/
<p>Apa itu Jekyll-admin?
Bagaimana cara install-nya?
Bagaima cara menggunakannya?</p>
<p>Silakan klik <a href="https://github.com/jekyll/jekyll-admin">DISINI</a></p>
Pengalalaman Belanja di Aliexpress Pembayaran Menggunakan Debit btn
2017-09-30T10:36:00+07:00
2017-09-30T10:36:00+07:00
Unknown
https://www.sumarsono.com/pengalalaman-belanja-di-aliexpress-pembayaran-menggunakan-debit-btn/
<p>Saya ingin membeli Lithium Battery Pack Expansion Board Power Supply with Switch untuk Raspberry Pi. Cari di olshop nasional, ada. Tapi harganya waw bikin tercenging, mahal beud. Coba cari di aliexpress, waw harganya selisih banyak, 50% lebih murah daripada di olshop nasional. Free ongkir pula. Saya putuskan untuk membeli dari aliexpress.</p>
<p>Mau bayar pakai apa? Dokuwallet sudah tida bisa dipakai karena harus upload KTP ke alipay untuk verifikasi. Males. Akhirnya saya memberanikan diri bayar pakai kartu debit BTN.</p>
<p>Caranya?</p>
<ol>
<li>Pas checkout pilih metode pembayaran lain</li>
<li>Kemudian masukan nomor kartu</li>
<li>Masukan tanggal/tahun kadaluarsa</li>
<li>masukan 3 digit angka di belakang kartu</li>
<li>profit</li>
<li>tinggal nunggu pembayaran di verifikasi</li>
</ol>
<p>Akhirnya setelah 3 minggu, barang pesanan saya datang diantarkan oleh Pak POS.</p>
Share Koneksi Internet WIFI via Ethernet di Arch Linux
2017-09-27T22:22:00+07:00
2017-09-27T22:22:00+07:00
Unknown
https://www.sumarsono.com/share-koneksi-internet-wifi-via-ethernet-di-arch-linux/
<p>Kamu ingin membagikan koneksi internet dari Wifi laptop ke LAN laptop?
Kamu pengguna distribusi Arch linux?
Kamu pengguna DE GNOME?</p>
<p>Jika iya, lanjutkan. Jika tidak? tetap lanjutkan.</p>
<h3 id="topologi-yang-saya-gunakan">Topologi yang saya gunakan</h3>
<p>Internet------(Wifi) laptop (LAN)------Raspberry Pi 3</p>
<h3 id="step-by-step">Step by step</h3>
<ol>
<li>Buka <code>nm-connection-editor</code></li>
<li>Klik <em>Add</em></li>
<li>Pilih <em>Ethernet</em></li>
<li>Klik <em>Create…</em></li>
<li>Klik <em>IPv4 Settings</em></li>
<li>Pilih <em>Shared to other computers</em> di menu Method</li>
<li>Masukan nama <em>share wifi ke lan</em> dalam kolom isian connection name</li>
<li>Profit</li>
</ol>
Repositori Sublime Text untuk Arch Linux
2017-09-21T15:10:00+07:00
2017-09-21T15:10:00+07:00
Unknown
https://www.sumarsono.com/repositori-sublime-text-untuk-arch-linux/
<p>Baru-baru ini <code>Sublime Text 3</code> diperbaharui oleh tim pengembang. <em>alhail freeware for linux</em>. Terimakasih untuk tim pengembang.</p>
<p>Dari kasus ini saya menjadi tahu kalau ternyata <code>Sublime Text</code> memiliki Repositori untuk linux, yang dapat diakses <a href="https://www.sublimetext.com/docs/3/linux_repositories.html">DISINI</a></p>
<p>Sekian.</p>
POSTROUTING Openwrt
2017-09-20T09:46:00+07:00
2017-09-20T09:46:00+07:00
Unknown
https://www.sumarsono.com/postrouting-openwrt/
<p>Melanjutkan [artikel tentang relayd]({% post_url 2017-09-19-tp-link-mr3420-v3-eu-wds-mode-dengan-firmware-lede %})</p>
<p>Pada artikel tersebut, IP 192.168.2.0/24 yang tercantum dalam gambar topologi belum dapat terhubung ke internet. IP yang terhubung internet adalah 192.168.1.0/24.</p>
<p>Apakah bisa 192.168.2.0/24 dibuat terhubung internet? Bisa. Sederhana saja, kita tambah chain <code>POSTROUTING</code> pada tabel <code>NAT</code> yang akan melakukan <code>MASQUERADE</code> dari 192.168.2.0/24 ke interface <code>wlan0</code>.</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>iptables -t nat -A POSTROUTING -s 192.168.2.0/24 -o wlan0 -j MASQUERADE
</span></code></pre>
<p>Profit</p>
TP-Link MR3420 V3 EU WDS Mode dengan firmware Lede
2017-09-19T17:26:00+07:00
2017-09-19T17:26:00+07:00
Unknown
https://www.sumarsono.com/tp-link-mr3420-v3-eu-wds-mode-dengan-firmware-lede/
<p><img src="/assets/images/802.11-routed-relay.webp" alt="802.11-routed-relay.webp" /></p>
<p>Melanjutkan petualangan saya bersama TP-Link MR3420 v3 EU. Ketika menggunakan firmware original dari TP-Link, Wireless router ini mempunyai fitur WDS. Jadi satu Wireless router menjadi <em>client</em> sekaligus <em>Access Point</em>. Topologinya seperti gambar diatas. Ketika saya berpindah ke firmware berbasis openwrt, saya merindukan fitur ini.</p>
<p>Apakah openwrt tidak punya fitur yang serupa? punya. Tapi saya tidak tahu, saya jadi tahu setelah bertanya di group <a href="https://t.me/pegelwrt">Telegram Openwrt & IoT</a>.</p>
<p>Caranya? Ikuti saja wiki <a href="https://wiki.openwrt.org/doc/recipes/relayclient">tentang relayd</a> ini.</p>
<p>Apakah ada kendala yang saya alami? Ada, berikut ini kendala yang saya alami:</p>
<ol>
<li>MR3420 V3 EU, penyimpanan internalnya sangat kecil sehingga tidak bisa dipasang <code>LUCI</code>.
<strong>Solusinya?</strong> Kongigurasi dari <code>cli</code>, bisa dengan konfigurasi cara edit file, bisa jugan menggunakan <a href="https://wiki.openwrt.org/doc/uci">UCI</a>.</li>
<li>Saya mengalami galat <code>unknown package relayd</code> ketika install paket <code>relayd</code>.
<strong>Solusinya?</strong> Tambah source list opkg dengan ini:</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>src/gz base http://downloads.lede-project.org/releases/17.01.1/packages/mips_24kc/base/
</span></code></pre>
<p>Selebihnya lancar.</p>
i3wm Second Display Only
2017-08-16T09:11:00+07:00
2017-08-16T09:11:00+07:00
Unknown
https://www.sumarsono.com/i3wm-second-display-only/
<p>Sudah 3 hari saya memakai i3wm di mesin arch linux saya. Bukan apa-apa sih, hanya iseng saja. Kebetulan hari ini, saya menghubungkan mesin ke external monitor yang resolusinya lebih besar yaitu 1440x900.</p>
<p>Sempat bingung, bagaimana caranya agar display di laptop mati, dan eksternal display ON karena secara default saya berada dalam mode <em>mirror</em>. Ternyata caranya cukup simple.</p>
<ol>
<li>jalankan <code>xrandr</code>
bash-script
[sumarsono@mesin-arch ~]$ xrandr
Screen 0: minimum 8 x 8, current 1440 x 900, maximum 32767 x 32767
LVDS1 connected primary (normal left inverted right x axis y axis)
1280x800 59.99 + 50.00<br />
1024x768 60.00<br />
800x600 60.32 56.25<br />
640x480 59.94<br />
640x400 60.00<br />
DP1 disconnected (normal left inverted right x axis y axis)
DP2 disconnected (normal left inverted right x axis y axis)
DP3 disconnected (normal left inverted right x axis y axis)
HDMI1 disconnected (normal left inverted right x axis y axis)
HDMI2 disconnected (normal left inverted right x axis y axis)
VGA1 connected 1440x900+0+0 (normal left inverted right x axis y axis) 420mm x 260mm
1440x900 59.90*+
1280x1024 60.02<br />
1280x800 59.81<br />
1152x864 75.00<br />
1280x720 60.00<br />
1024x768 75.03 60.00<br />
832x624 74.55<br />
800x600 75.00 60.32 56.25<br />
640x480 75.00 59.94<br />
720x400 70.08<br />
VIRTUAL1 disconnected (normal left inverted right x axis y axis)
[sumarsono@mesin-arch ~]$</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>2. jalankan perintah berikut agar VGA1 hidup dab LVDS1 Matikan
</span><span>bash-script
</span><span>xrandr --output VGA1 --mode 1440x900 --output LVDS1 --off
</span></code></pre>
<ol start="3">
<li>Profit !</li>
</ol>
Install Firmware berbasis OpenWrt di TP-Link MR3420 V3 EU
2017-08-16T07:29:00+07:00
2017-08-16T07:29:00+07:00
Unknown
https://www.sumarsono.com/install-firmware-berbasis-openwrt-di-tp-link-mr3420-v3-eu/
<p>Saya punya mainan baru, Wireless router merk TP-LINK. Tipe MR3420 v3 (EU version). Penasaran apakah router ini bisa di ganti firmware-nya ke firmware berbasis openwrt, akhirnya saya browsing. Dan ternyata bisa, walaupun belum official dan belum seramai seri pendahulunya, v1 dan v2.</p>
<p>Alkisah, saya berhasil memasang firmware dari <a href="http://pulpstone.pw">pulpstone</a>, dia berbasis openwrt dan yang membuat adalah orang Indonesia. Ikut bangga. Akan tetapi tidak semulus tutorial yang ditulis di <a href="http://pulpstone.pw">pulpstone</a>, karena punya saya versi EU, tidak bisa langsung flash dari menu <code>system upgrade</code> di dashboard TP-LINK.</p>
<p>Urutan keberhasilan saya adalah seperti ini:</p>
<ol>
<li>Gunakan firmware <a href="https://success.tanaza.com/s/ap/a0B5700001gL62fEAC/tplink-tlmr3420-v3">Tanaza EU version</a> dengan cara flash dari menu <code>system upgrade</code> di dashboard TP-LINK. <code>Tanaza</code> ini berbasis openwrt juga. Kalau kesulitan mendapatkan firmware dari tanaza, silakan gabung ke <a href="https://t.me/pegelwrt">group Telegram Pegel WRT & IoT</a> kemudian cari files-nya disana.</li>
<li>Upload firmware dari <a href="http://pulpstone.pw">pulpstone</a> ke direktori <code>/tmp/</code> Tanaza.</li>
<li>Masuk ke sesi <code>ssh</code> Tanaza dengan <code>user: admin</code> dan <code>pass: tanaza</code></li>
<li>Lakukan penulisan firmware pakai command <code>mtd</code></li>
<li>Tunggu hingga selesai dan reboot otomatis.</li>
<li>Selesai. Silakan login ke pulpstone dengan <code>user: root</code> dan <code>pass: root</code></li>
</ol>
Debrick TP-LINK MR3420 V3 EU yang gagal Flash Firmware berbasis OpenWrt
2017-08-16T07:14:00+07:00
2017-08-16T07:14:00+07:00
Unknown
https://www.sumarsono.com/debrick-tp-link-mr3420-v3-eu-yang-gagal-flash-firmware-berbasis-openwrt/
<p>Setelah saya berhasil flash <a href="http://pulpstone.pw">pulpstone</a>, saya penasaran dengan firmware keluaran <a href="https://ofmodemsandmen">ofmodemsandmen</a> yaitu <code>GoldenOrb</code>. Saya cek disana, ternyata ada untuk TP-LINK MR3420 V3, hanya saja tidak jelas bisa untuk versi EU atau tidak.</p>
<p>Modal nekat, coba flash pakai <code>mtd</code>, eh ternyata routernya K.O. Led indikator tidak menyala sama sekali.</p>
<p>Dengan harapan si router masih bernyawa, saya mencoba mengubungkan port wan ke laptop, menekan dan menahan tombol reset 5-10 detik, kemudian menekan tombol ON pada router, led indikator LAN di laptop berkedip, wah ada komunikasi. Akhirnya saya gunakan <code>wireshark</code> untuk menangkap informasi dari port lan.</p>
<p>Dari informasi yang ditangkap <code>wireshark</code> saya baca baris demi baris, ada informasi berikut ini:</p>
<ol>
<li>Who has <code>192.168.0.66</code>? Tell <code>192.168.0.86</code>.</li>
<li>Read Request, File: <code>mr3420v3_tp_recovery.bin</code>, Tansfer type: octet, timeout=2. Dengan protokol <code>tftp</code>.</li>
</ol>
<p>Wow, ternyata router saya masih hidup. Dari informasi diatas dapat disimpulkan sebagai berikut:</p>
<ol>
<li>Router menggunakan IP 192.168.0.86 pada port wan.</li>
<li>Router mencari IP 192.168.0.66.</li>
<li>Router mencari file dengan nama <code>mr3420v3_tp_recovery.bin</code> yang akan diambil pakai protokol <code>tftp</code></li>
</ol>
<p>Dari situ, kita cukup turuti kemauan si router.</p>
<ol>
<li>Set IP Address komputer kita menjadi 192.168.0.66</li>
<li>Siapkan <code>tftp server</code> pada komputer kita, terserah pakai program apa, sesuaikan dengan OS.</li>
<li>Download firmware original dari TP-Link dan rename menjadi <code>mr3420v3_tp_recovery.bin</code> kemudian taruh di direktori root tftp server.</li>
<li>Matikan router.</li>
<li>Tekan dan tahan tombol reset pada router.</li>
<li>Tekan tombol ON pada router.</li>
<li>Tunggu 5-10 detik kemudian lepaskan tombol reset.</li>
<li>Cek log tftp server, apakah ada komunikasi dari router, kalau ada, biarkan saja.</li>
<li>Tunggu 1-5 menit sampai router reboot otomatis.</li>
<li>Jreng jreng, router hidup lagi.</li>
<li>Login ke dashboard TP-Link dengan <code>user: admin</code> dan <code>pass: admin</code></li>
<li>Selesai.</li>
</ol>
Mudah Download Xcode 9 Beta 5 dengan Resume Support
2017-08-14T13:22:00+07:00
2017-08-14T13:22:00+07:00
Unknown
https://www.sumarsono.com/mudah-download-xcode-9-beta-5-dengan-resume-support/
<p>Tiga hari ini, saya mencoba download Xcode 9 beta 5 yang berukuran segede gaban 0dan berkali kali menemui kegagagalan. Dan baru siang ini sukes. File berukuran 4.9GB ini akhirnya sukses masuk dalam penyimpanan pribadi saya.</p>
<p>Kendala yang saya temui adalah tidak bisa resume download yang terputus, berbagai download manager saya coba, seperti bawaan Safari, bawaan firefox, Downthemall, dan Folx. Semuanya tidak cocok dengan CDN <code>developer.apple.com</code> yang menggunakan auth berdasarkan cookie dari browser.</p>
<p>Jadi kita login ke <code>developer.apple.com</code>-->browser menyimpan cookie-->Download dimulai. Begitu cookie dalam browser expired, maka download tidak dapat dilanjutkan. Bagi saya yang kecepatan unduhan tidak secepat <em>the flash</em> benar-benar kerepotan.</p>
<p>Sampai akhirnya saya jengkel dan mencari solusi, baru siang ini secara tidak sengaja saya menemukan tulisan <a href="http://iandundas.com/blog/2017/2/21/script-for-reliably-and-quickly-downloading-xcode-on-a-poor-connection">Ian Dundas</a>. Beliau menulis script <code>ruby</code>untuk dowload xcode. <strong>He is my lifesaver</strong>. Thank you <a href="http://iandundas.com/blog/2017/2/21/script-for-reliably-and-quickly-downloading-xcode-on-a-poor-connection">Ian</a>.</p>
<p>Saya hanya perlu mengubah sedikit script-nya agar sesuai dengan keadaan saya, dan akhirnya xcode terdownload dengan selamat. Ringkasnya yang saya lakukan adalah sebagai berikut:</p>
<ol>
<li>Pasang extensi <a href="https://bitstorm.org/extensions/view-cookies/">View Cookies</a> untuk firefox.</li>
<li>Copy script <a href="http://iandundas.com/blog/2017/2/21/script-for-reliably-and-quickly-downloading-xcode-on-a-poor-connection">Ian Dundas</a> simpan sebagi <code>download_xcode.rb</code></li>
<li>Edit script tersebut</li>
<li>Buka firefox, kemudian buka https://developer.apple.com/download/</li>
<li>Login dengan akun apple id</li>
<li>Klik Download kemudian klik save File</li>
<li>Show all download pada firefox, kemudian pada proses download xcode, klik kanan, copy download link. Milik saya ini https://download.developer.apple.com/Developer_Tools/Xcode_9_beta_5/Xcode_9_beta_5.xip linknya.</li>
<li>Jalankan script <code>download_xcode.rb</code></li>
<li>Akan diminta memasukan download link, paste link tadi.</li>
<li>kemudian akan diminta untuk memasukan cookie <code>ADCDownloadAuth</code></li>
<li>Kembali ke halaman https://developer.apple.com/download/ kemudian tekan <code>cmd</code>+<code>i</code>, masuk ke tab Cookies</li>
<li>Cari cookie bernama <code>ADCDownloadAuth</code> dan copy <code>value</code>-nya</li>
<li>Selesai, download akan dimulai dengan resume support.</li>
</ol>
Laptop dengan Kerusakan pada CPU's Decoupling Capacitor
2017-07-27T18:13:00+07:00
2017-07-27T18:13:00+07:00
Unknown
https://www.sumarsono.com/laptop-dengan-kerusakan-pada-cpu-s-decoupling-capacitor/
<p>Jikalau laptop engkau mengalami gejala berikut:</p>
<ul>
<li>Random reboot</li>
<li>Random BSOD</li>
<li>Tidak bisa masuk ke OS Linux meskipun via flashdisk</li>
<li>Random BSOD ketika install OS Windows</li>
<li>Kadang tidak mau di charge padahal baterai normal</li>
<li>Kadang tidak mau masuk windows saat di charge.</li>
</ul>
<p>Besar kemungkinan laptop tersebut rusak Kapasitornya, lebih spesifik CPU's Decoupling Capasitor. Solusi tercepat jika tidak punya uang (atau alasan lain) untuk menggantinya, cobalah untuk hanya mengaktifkan satu core cpu saja di bios. Jika beruntung, laptop masih bisa boot ke OS walaupun kinerja menurun.</p>
<p>Semoga bermanfaat</p>
Mengatasi Reminder Aktifasi Office 365 yang Muncul Berulang-ulang
2017-07-26T11:14:00+07:00
2017-07-26T11:14:00+07:00
Unknown
https://www.sumarsono.com/mengatasi-reminder-aktifasi-office-365-yang-muncul-berulang-ulang/
<p><img src="/assets/images/365.webp" alt="Reminder Office 365" /></p>
<p>Kemarin, dapat Lenovo AIO PC yang mana sudah terpasang Windows 10 Home. Umumnya <em>unboxing</em>, buka kardus dan tes Power ON. Begitu hidup, akan diarahkan untuk <em>setup</em> akun Window dan Lenovo ID.</p>
<p>Terlalu panjang <em>Skip Skip</em>...................</p>
<p>Singkat cerita, ada office 365 didalamnya, saya buang dan ganti Office 2016. Setelah Windows dan Office saya aktifkan via internet, eh ada yang ngeselin. Setiap buka aplikasi Office, selalu muncul peringatan untuk aktifasi Office 365. Sungguh <em>shitty shit</em> dan <em>annoying</em>. Di restart masih sama saja.</p>
<p>Coba <em>browsing</em>, dengan kata kunci "annoying office 365 activation reminder" dan ternyata ada yang mengalami hal yang sama, dan sudah ada solusinya. Berikut saya kutip dari <a href="https://support.microsoft.com/en-us/help/3170450/repeated-activation-prompts-occur-after-installing-volume-license-vers">sini</a></p>
<p>To resolve this problem, export the following registry keys and delete from computer.</p>
<ol>
<li>Close activation screen.</li>
<li>On the Start menu, click Run.</li>
<li>Type regedit, and then press Enter.</li>
<li>Select the following key in the registry.</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Office\16.0\Common\OEM
</span></code></pre>
<ol start="5">
<li>Right click the OEM value and click File>Export.</li>
<li>Save the key</li>
<li>Once the key is backed-up, click on Edit>Delete</li>
<li>Repeat steps 4-7 with following key</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\16.0\Common\OEM
</span></code></pre>
<ol start="9">
<li>Exit Registry Editor</li>
</ol>
<p>restart dan selesai.</p>
<p>Semoga bermanfaat.</p>
Mengatasi Galat can't open device /dev/ttyACM0: Permission denied Ketika Upload Program ke Arduino dari Arch Linux
2017-07-17T20:49:00+07:00
2017-07-17T20:49:00+07:00
Unknown
https://www.sumarsono.com/mengatasi-galat-can-t-open-device-dev-ttyacm0-permission-denied-ketika-upload-program-ke-arduino-dari-arch-linux/
<p>Ceritanya, malam ini saya mendapat rongsokan <code>Arduino Mega 250</code> dari tukang rongsokan, secara <em>free</em> alias gratis. Namanya barang gratis, kalau normal ya Alhamdulillah, kalau rusak ya sudah tidak mengapa.</p>
<p>Langsung ambil kabel USB dan tancap ke mesin Arch Linux. Si Arduino ini, sifatnya <em>masukan dan mainkan</em> ketika dipasang di mesin berbasis GNU/Linux. Langsung terdeteksi sebagai:
bash
Bus 006 Device 004: ID 2341:0042 Arduino SA Mega 2560 R3 (CDC ACM)</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>
</span><span>Dulu, ketika masih menggunakan Ubuntu, saya harus membuat `udev rule` untuk proses baca tulis ke Arduino. Bagaimana dengan Arch Linux? Saya coba langsung _fire in the hole_ saja pakai aplikasi `Arduino IDE`. Eh..muncul error:
</span><span>bash
</span><span>can't open device "/dev/ttyACM0": Permission denied
</span></code></pre>
<p>Solusinya mudah saja, tinggal masukin aja user kita ke group <code>uucp</code></p>
<p>bash
sudo usermod -a -G uucp</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>
</span><span>Coba upload lagi programnya, dan tara...berhasil...
</span><span>
</span><span>
</span><span>Terimakasih
</span></code></pre>
Akses Android MTP di OS X
2017-07-16T16:54:00+07:00
2017-07-16T16:54:00+07:00
Unknown
https://www.sumarsono.com/akses-android-mtp-di-os-x/
<p><img src="/assets/images/filetransfer.webp" alt="filetransfer" /></p>
<p>Secara <em>default</em> ketika kita menghubungkan device android ke PC melalui sambungan USB, akan <em>termount</em> sebagai MTP device. Namun berbeda dengan yang terjadi di mesin MAC.</p>
<p>Untuk mengakses MTP di mesin MAC, kita harus memanfaatkan Aplikasi <code>androidfiletransfer</code>.
Aplikasi tersebut dapat diunduh dari <a href="https://www.android.com/filetransfer/">sini</a></p>
<h2 id="how-to-use-it">How to use it</h2>
<ol>
<li>Download the app.</li>
<li>Open <code>androidfiletransfer.dmg</code>.</li>
<li>Drag <code>Android File Transfer</code> to <code>Applications</code>.</li>
<li>Use the USB cable that came with your Android device and connect it to your Mac.</li>
<li>Double click <code>Android File Transfer</code>.</li>
<li>Browse the files and folders on your Android device and copy files up to 4GB.</li>
</ol>
<p>Terimakasih</p>
Mudah! Mencari Driver Printer Canon dengan Cepat
2017-07-13T18:43:00+07:00
2017-07-13T18:43:00+07:00
Unknown
https://www.sumarsono.com/mudah-mencari-driver-printer-canon-dengan-cepat/
<p>Langsung saja <a href="http://support-id.canon-asia.com/?personal">kesini</a></p>
Google Chrome Standalone Installer
2017-07-13T18:28:00+07:00
2017-07-13T18:28:00+07:00
Unknown
https://www.sumarsono.com/google-chrome-standalone-installer/
<p><img src="/assets/images/chrome-offline-installer.webp" alt="Chrome" />
Rasa-rasanya sudah sangat lama tidak menggunakan sistem operasi microsoft Windows. Sampai-sampai mau install google chrome saja <em>kesusahan</em>. Setelah mengunjungi situsnya google Chrome, ternyata installernya harus <em>online</em>.</p>
<p>Langsung saja nge <a href="https://duckduckgo.com/?q=chrome+standalone&bext=lfa&atb=v71-6&ia=web">DDG</a> untuk mencari installer google chrome yang offline. Dan ketemu <a href="https://productforums.google.com/forum/#!topic/chrome/bKGfrds1r78">diskusi ini</a>. Ternyata untuk mengunduh chrome standalone installer harus <a href="https://www.google.com/chrome/browser/desktop/index.html?standalone=1">kesini</a></p>
<p>Tulisan ini saya tulis untuk catatan pribadi saja. Semoga kelak berguna.</p>
<p>Terimakasih</p>
Mudah! Dualboot Remix OS dengan Arch Linux
2017-07-05T20:51:00+07:00
2017-07-05T20:51:00+07:00
Unknown
https://www.sumarsono.com/mudah-dualboot-remix-os-dengan-arch-linux/
<p><img src="/assets/images/remixos-2.webp" alt="Remix OS-1" /></p>
<p>Siang tadi, saya sedikit senggang. Kesempatan itu saya gunakan untuk mencoba install Remix OS di Thinkpad x200. Iseng saja sebenarnya, ingin tahu seperti apa rasanya menjalankan Remix OS di laptop tua.</p>
<p>Remix OS merupakan sistem operasi Android yang dimodifikasi sehingga tampilannya mirip dengan sistem operasi besutan Microsoft. Namun sayangnya, Remix OS ini sudah berhenti dikembangkan. Selengkapanya silakan kunjungi <a href="http://jide.com">jide.com</a>.</p>
<p>Thinkpad x200 milik saya, sudah terpasang sistem operasi Arch Linux. Jadi, akan saya dualboot dengan Remix OS. Caranya sangat mudah, sama halnya dengan proses dualboot dengan Android X86. Berikut ini langkah sayang saya ambil:</p>
<ol>
<li>Download File Remix OS <a href="https://www.fosshub.com/Remix-OS.html">disini</a></li>
<li>Ekstrak hasil download tadi, maka akan didapat berkas-berkas berikut ini:
bash
[sumarsono@mesin-arch Remix_OS_for_PC_Android_M_32bit_B2016112201]$ tree
.
├── How_to_launch_Remix_OS_for_PC.txt
├── md5sum.txt
├── Remix_OS_for_PC_Android_M_32bit_B2016112201.iso
└── Remix_OS_for_PC_Installation_Tool-B2016080802.exe
0 directories, 4 files</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>3. Siapkan satu partisi `EXT4`, milik saya `sda4` sebesar 10GB. Dijadikan satu dengan partisi `/` milik arch juga boleh. Jangan lupa set `bootable` jika menggunakan partisi terpisah.
</span><span>bash
</span><span>/dev/sda4 * 213958656 234438655 20480000 9,8G 83 Linux
</span></code></pre>
<ol start="4">
<li>Mount berkas <code>Remix_OS_for_PC_Android_M_32bit_B2016112201.iso</code> hasil ekstrak tadi.
bash
fuseiso /direktori/hasil/ekstrak/Remix_OS_for_PC_Android_M_32bit_B2016112201/Remix_OS_for_PC_Android_M_32bit_B2016112201.iso /lokasi/yg/mau/dijadika/tempat/mount/</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>Dalam hal ini, saya menggunakan `fuseiso`. Boleh menggunakan tool lain. Punya saya, saya mount ke `/home/sumarsono/ISO/`.
</span><span>5. Masuk ke direktori `/dev/sda4` kemudian buat folder dengan `RemixOS/data/`
</span><span>6. Kembali ke `/home/sumarsono/ISO/` kemudian copy file berikut ini kemudian paste ke `/dev/sda4/RemixOS`:
</span><span> - initrd.img
</span><span> - isolinux.sys
</span><span> - kernel
</span><span> - ramdisk.img
</span><span> - system.sfs,
</span><span> Sehingga isi dari `/dev/sda4` adalah sebagai berikut:
</span><span> bash
</span><span> .
</span><span> └── RemixOS
</span><span> ├── data
</span><span> ├── initrd.img
</span><span> ├── isolinux.sys
</span><span> ├── kernel
</span><span> ├── ramdisk.img
</span><span> └── system.sfs
</span><span> 3 directories, 5 files
</span><span> ```
</span><span>7. Kemudian edit file `/etc/grub.d/40_custom`, tambahkan:
</span><span>bash
</span><span>menuentry "Remix OS" {
</span><span> set root='(hd0,4)' #sesuaikan dengan partisi yang disiapkan
</span><span> linux /RemixOS/kernel quiet root=/dev/ram0 SERIAL=random logo.showlogo=$
</span><span> initrd /RemixOS/initrd.img
</span><span>}
</span></code></pre>
<ol start="8">
<li>update <code>grub.cfg</code>
bash
sudo grub-mkconfig -o /boot/grub/grub.cfg</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>10. Reboot, and viola ! sudah bisa boot ke Remix OS
</span><span>
</span><span>Screenshot:
</span><span>
</span><span>![Remix OS-2](/assets/images/remixos-1.webp)
</span><span>
</span><span>![Remix OS-3](/assets/images/remixos-3.webp)
</span><span>
</span><span>Mudah bukan? selamat mencoba
</span></code></pre>
Backup Partisi Root Arch Linux Menggunakan Gnome Disk
2017-07-04T08:57:00+07:00
2017-07-04T08:57:00+07:00
Unknown
https://www.sumarsono.com/backup-partisi-root-arch-linux-menggunakan-gnome-disk/
<p>Saya berniat memindahkan sistem operasi Arch Linux yang saya gunakan ke SSD lain, sehingga saya tidak perlu <em>setup</em> arch linux dari awal. <em>setup</em> arch linux dari awal itu sangat <em>wasting time</em> dan boros kuota. Alih alih mau produktif malah jadi kontra produktif.</p>
<p>Kronologi:</p>
<ol>
<li>Backup partisi Root</li>
<li>Simpan ke HDD eksternal</li>
<li>Pasang SSD baru</li>
<li>Restore partisi Root</li>
<li>Install dan konfigurasi grub</li>
</ol>
<p>Oleh sebab itu, kenapa tidak <em>clone</em> aja systemnya, begitu di <em>restore</em> sudah tidak ribet <em>setup</em> ini itu.
Dari banyak referensi <em>clone</em>, saya memilih menggunakan <code>dd</code> karena built in dalam sistem operasi GNU/Linux secara umum. Ditambah lagi, DE Gnome-shell yang saya gunakan sudah ada <em>frontend</em> untuk <code>dd</code> yakni <code>gnome-disk</code>. Tentu saja enak dan mempercepat proses, tinggal klik klik tunggu dan selesai.</p>
<p>Nah, untuk menghindari galat yang tidak saya inginkan, maka saya melakukan <em>clone</em> dari <em>live system</em> GNU/Linux. Berikut ini prosesnya:</p>
<ol>
<li>Boot dari live systemnya</li>
<li>Buka gnome-disk
<img src="/assets/images/gnome-disk-c.webp" alt="Gnome Disk" /></li>
</ol>
<p>Nah langkah selanjutnya:</p>
<ol>
<li>Klik Disk yang mau di backup partisinya</li>
<li>Klik Partisi yang mau di Backup</li>
<li>Klik ikon gear</li>
<li>Klik create partition image</li>
<li>Kemudian tentukan lokasi penyimpanan dan beri nama filenya.</li>
<li>Selesai.</li>
</ol>
<p>Untuk proses <em>restore</em> akan saya tulis dalam artikel lain.</p>
<p>Terimakasih</p>
Backup Bootloader Arch Linux
2017-06-27T20:46:00+07:00
2017-06-27T20:46:00+07:00
Unknown
https://www.sumarsono.com/backup-bootloader-arch-linux/
<p>I have a big plan for my old laptop. So I need to backup entire <code>root</code> partition. Of course I need to backup my <code>bootloader</code>, too. In this articel, I will write how to backup <code>bootloader</code> only.</p>
<p>I did this in my Arch Linux machine, but I'm pretty sure this is relevant to another gnu/linux distro. I must warn you, that I not yet try to restore from this backup procedure.</p>
<p>Here what i did:</p>
<ol>
<li>Open my <code>gnome-terminal</code></li>
<li>Issue this command:
bash
sudo dd if=/dev/sda of=/home/sumarsono/bootloader_arch_sumar bs=446 count=1</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>Here the output:
</span><span>bash
</span><span>[sudo] password for sumarsono:
</span><span>1+0 records in
</span><span>1+0 records out
</span><span>446 bytes copied, 0,000302793 s, 1,5 MB/s
</span></code></pre>
<p>Done</p>
<p>Why <code>bs=446</code>? You can found the information <a href="https://en.wikipedia.org/wiki/Master_boot_record#Sector_layout">here</a></p>
<p>At last but not least, Sorry for my bad english.</p>
Ada yang Salah dengan Idulfitri-ku
2017-06-26T10:03:00+07:00
2017-06-26T10:03:00+07:00
Unknown
https://www.sumarsono.com/ada-yang-salah-dengan-idulfitri-ku/
<p>Saya akan membuka artikel ini dengan mengucapkan <strong>Selamat Idulfitri</strong>. Saya selaku admin <a href="https://www.sumarsono.id">sumarsono.id</a> memohon maaf kepada semua pengunjung situs ini.</p>
<p>Sesuai dengan judul dan tag, artikel ini berbeda dengan artikel yang biasa saya tulis. Saya akan curhat. Idulfitri, dari saya kecil sampai saya berusia 25 tahun, <em>ceremony</em>-nya selalu sama.</p>
<p>Namun, pada Idulfitri tahun ini saya merasa ada yang ganjil, ada yang salah, ada yang kurang, ada yang tidak beres. Perasaan mengganjal itu, sedikit sulit diungkap dengan kata. Saya bahkan tidak mampu merangkai analogi yang bisa mewakili.</p>
<p>Namun, ada yang menonjol, ada yang bisa disampaikan ke dunia. Hati saya tidak bergetar ketika gema takbir membelah seantero kampung. Padahal, pada saat Idulfitri sebelumnya begitu bergetar, ingin menangis saking bergetarnya. Namun tahun ini begitu hampa, tidak ada getaran, tidak ada rasa, kosong.</p>
<p>Saya terus memikirkan hal ini, bersemedi dalam keramaian, mencari jawaban atas apa yang menimpaku.</p>
<p>Mungkin hati ini telah mengeras. Mungkin hati ini telah membatu. Mungkin hati ini telah gelap tertutup dosa, dosa yang pekat, dosa yang menjadi tabir dari cahaya. Sehingga hati ini tak lagi bergetar ketika gema takbir berkumandang.</p>
<p>Mungkin puasaku hanya dapat lapar dan dahaga. Mungkin saya tak mencapai <em>fitri</em>. Sampai takbir tak menggetarkan hati.</p>
<p>Saya hanya berharap, Tuhan mengampuni saya.</p>
K-9 Mail dan Verifikasi Dua Langkah Google
2017-06-10T04:15:00+07:00
2017-06-10T04:15:00+07:00
Unknown
https://www.sumarsono.com/k-9-mail-dan-verifikasi-dua-langkah-google/
<p>Yesterday, saya merasa gerah dengan aplikasi Gmail untuk Android. Notifikasi email masuknya telat, menunggu aplikasinya dibuka dulu. Setelah saya telaah, ternyata aplikasi Gmail ini lumayan <em>rakus</em> penggunaan RAM-nya, maklum HP saya HP <em>low end</em> dengan spesifikasi rendah.</p>
<p>Oleh sebab itu, saya mencari aplikasi <em>email client</em> yang ringan. Akhirnya ketemu dengan <a href="https://play.google.com/store/apps/details?id=com.fsck.k9&hl=en">K-9 Mail</a>. Ukurannya kecil.</p>
<p>Selesai unduh, langsung saya coba untuk masuk menggunakan akun Gmail saya, eh gak bisa login, dan tidak ada pesan error apapun. Setelah browsing, ternyata hal itu terjadi karena terkendala Verifikasi 2 langkah Google.</p>
<p>Nah, berikut ini langkah setup K-9 Mail untuk akun Google:</p>
<ol>
<li>Kunjungi <a href="https://www.google.com/settings/account">Google Account settings page.</a>.</li>
<li>Klik <strong>Sign-in & Security</strong></li>
<li>Di bagian <strong>Password & sign-in method</strong>, klik <strong>App Passwords</strong></li>
<li>Di bawah tulisan <strong>Select the app and device you want to generate the app password</strong>, klik <strong>Select App</strong> kemudian klik <strong>other <em>(custom name)</em></strong></li>
<li>Masukan nama, misalnya <em>K-9 Mail Android</em></li>
<li>Klik <strong>GENERATE</strong> sehingga muncul <em>pop up</em> <strong>Generated app password</strong></li>
<li>Gunakanlah password yang muncul tersebut untuk login di Aplikasi K9-Mail.</li>
<li>Selesai</li>
</ol>
<p>Semoga bermanfaat</p>
Menambah 'Indonesia' di Setting Region & Language Arch Linux
2017-05-29T09:34:00+07:00
2017-05-29T09:34:00+07:00
Unknown
https://www.sumarsono.com/menambah-indonesia-di-setting-region-language-arch-linux/
<p>Ketika saya melakukan pemasangan Arch Linux, <code>locale</code> yang saya gunakan dan saya <em>generate</em> hanyalah <code>en_US.UTF-8 UTF-8</code>. Hal ini tentu saja akan menyebabkan isi dari setting <code>Region and Language</code> hanya ada <code>English</code> dan <code>US</code>.</p>
<p>Saya ingin, untuk bagian <code>format</code> menggunakan Indonesia, nah yang saya lakukan adalah berikut ini:</p>
<ol>
<li>Buka file <code>/etc/locale.gen</code></li>
<li>Cari baris <code>#id_ID.UTF-8 UTF-8</code> dan hapus tanda <code>#</code> -nya kemudian simpan</li>
<li>Selanjutnya jalankan <code>locale-gen</code>
bash
sudo locale-gen</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>4. Buka setting `Region and Language`, sudah ada __Indonesia__ disana.
</span><span>
</span><span>![Region and Language]({{ site.baseurl}}/assets/images/region-and-language.webp)
</span></code></pre>
Pacman Cheat Sheet
2017-05-27T11:52:00+07:00
2017-05-27T11:52:00+07:00
Unknown
https://www.sumarsono.com/pacman-cheat-sheet/
<p>Saya adalah new comer di dunia Arch Linux. Sebagai pemula, tentu mengalami kendala.
Sebelum menggunakan Arch Linux, saya menggunakan Fedora. Sebelum menggunakan Fedora saya menggunakan Ubuntu.</p>
<p>Semua distribusi linux yang saya sebutkan tadi, memiliki <em>package manager</em> yang berbeda. Ubuntu menggunakan <code>apt</code>, Fedora menggunakan <code>dnf</code> (dulu <code>yum</code>), nah Arch Linux ini menggunakan <code>pacman</code>.</p>
<p>Untuk mempermudah proses belajar, saya mencari cheat sheet untuk <code>pacman</code> menggunakan <a href="https://duckduckgo.com/?q=pacman+cheatsheet&t=ffab&atb=v66-2&ia=cheatsheet">ddg</a>. Hasil pencarian itu, membuahkan hasil yang menarik. Berikut ini saya bagikan hasilnya:
![Pacman's Cheat Sheet]({{ site.url }}/assets/images/pacman-cheatsheet.webp)</p>
<p>Semoga bermanfaat.</p>
Jekyll di Arch Linux
2017-05-27T10:51:00+07:00
2017-05-27T10:51:00+07:00
Unknown
https://www.sumarsono.com/jekyll-di-arch-linux/
<ul>
<li>Kamis, 25 Mei 2017 saya melakukan pemasangan Arch Linux untuk menggantikan Fedora 25.</li>
<li>Jumat, 26 Mei 2017, Arch Linux di mesin saya, sudah siap digunakan.</li>
<li>Sabtu, 27 Mei 2017, Saya ingin melanjutkan penulisan artikel untuk <a href="https://www.sumarsono.id">sumarsono.id</a></li>
</ul>
<p><a href="https://www.sumarsono.id">sumarsono.id</a> ini dibangun menggunakan Jekyll, maka saya perlu setup jekyll untuk mesin Arch Linux saya. Berikut ini, langkah-langkahnya:</p>
<ol>
<li>Install <code>ruby</code> karena kita butuh <code>RubyGems</code>:
bash
sudo pacman -S ruby</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>
</span><span>2. Selanjutnya edit `.bashrc` dan tambahkan:
</span><span>bash-script
</span><span>PATH="$(ruby -e 'print Gem.user_dir')/bin:$PATH"
</span></code></pre>
<ol start="3">
<li>restart terminal</li>
<li>Update paket <code>gem</code>:
bash
gem update</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>5. Install `bundler` dan `jekyll`
</span><span>bash
</span><span>gem install jekyll bundler
</span></code></pre>
<ol start="6">
<li>Masuk ke direktori <em>static site</em> milik kita dan install paket yang diperlukan:
bash
bundle install</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>6. Setelah selesai, coba run _static site_ kita secara lokal
</span><span>bash
</span><span>bundle exec jekyll serve
</span></code></pre>
<p>Kalau berhasil run, berarti sudah beres. :+1:</p>
Mengganti Akes Github dari HTTPS ke SSH
2017-05-25T10:14:34+07:00
2017-05-25T10:14:34+07:00
Unknown
https://www.sumarsono.com/mengganti-akes-github-dari-https-ke-ssh/
<p>Selama ini, aktivitas terkait <code>git</code> selalu saya lakukan <em>over</em> <code>https</code>. Sampai akhirnya saya jenuh setiap kali harus menulis <code>username</code> dan <code>password</code>.</p>
<p>Kejenuhan nan mengikat itu yang membuat saya akhirnya berpaling dari <code>https</code> ke <code>ssh</code>. memindah akses via <code>https</code> ke <code>ssh</code> sangatlah mudah di git. Setelah kita selesai setup <code>key</code> di mesin kita dan di Github.com, langkah selanjutnya adalah mengubah <code>remote url</code> di mesin lokal.</p>
<p>Caranya:</p>
<ol>
<li>Buka terminal.</li>
<li>Cek <code>remote url</code> yang sekarang:</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>git remote -v
</span></code></pre>
<p>Output jika masih pakai https:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>origin https://github.com/username/nama-repo.git (fetch)
</span><span>origin https://github.com/username/nama-repo.git (push)
</span></code></pre>
<ol start="3">
<li>Ubah ke <code>ssh</code> dengan menggunakan <code>remote set-url</code> :</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>git remote set-url origin git@github.com:username/nama-repo.git
</span></code></pre>
<p>output dari <code>git remote -v</code> nanti akan berubah menjadi:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>origin git@github.com:username/nama-repo.git (fetch)
</span><span>origin git@github.com:username/nama-repo.git (push)
</span></code></pre>
<p>Sekian</p>
Menambah Tag dalam Situs Jekyll
2017-05-25T09:10:39+07:00
2017-05-25T09:10:39+07:00
Unknown
https://www.sumarsono.com/menambah-tag-dalam-situs-jekyll/
<p>Kemarin pagi, dihari yang cerah nan hangat, terlintas dalam pikiran saya <a href="https://www.sumarsono.id">sumarsono.id</a> kalau diberi <em>tagging</em> sepertinya keren.</p>
<p>Siangnya, di hari nan panas saya mencari referensi dan menemukan situs yang mengerti apa yang ada dalam benak saya kala itu, yakni situsnya <a href="http://charliepark.org/tags-in-jekyll/">charli</a> dan situsnya <a href="http://pavdmyt.com/how-to-implement-tags-at-jekyll-website/">Pavel D</a>. Awesome.</p>
<p>Di malam nan dingin merasuk sukma, saya mewujudkan angan. Dari dua referensi, saya menerapkan <em>tagging</em> yang ditulis <a href="http://pavdmyt.com/how-to-implement-tags-at-jekyll-website/">Pavel D</a> dengan sedikit modifkasi agar pas dengan <a href="https://www.sumarsono.id">sumarsono.id</a>. Berikut ini rangkumannya:</p>
<p>1.Beri <code>tags</code> pada setiap <code>front matter</code> masing-masing artikel yang kita tulis. Contohnya:</p>
<p>{% raw %}</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>---
</span><span>layout: post
</span><span>title: "Menambah Tag dalam Situs Jekyll"
</span><span>date: 2017-05-25 09:10:39
</span><span>tags: [jekyll]
</span><span>---
</span></code></pre>
<p>{% endraw%}</p>
<p>2.edit <code>_layout/post.html</code>, tambahkan:</p>
<p>{% raw %}</p>
<pre data-lang="html" style="background-color:#fcf0ca;color:#282828aa;" class="language-html "><code class="language-html" data-lang="html"><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">ul </span><span style="color:#407959;">class=</span><span style="color:#79740e;">"tags"</span><span style="color:#076678;">>
</span><span> {% for tag in page.tags %}
</span><span> </span><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">li</span><span style="color:#076678;">><</span><span style="font-weight:bold;color:#407959;">a </span><span style="color:#407959;">href=</span><span style="color:#79740e;">"/tags#{{ tag }}" </span><span style="color:#407959;">class=</span><span style="color:#79740e;">"tag"</span><span style="color:#076678;">></span><span>{{ tag }}</span><span style="color:#076678;"></</span><span style="font-weight:bold;color:#407959;">a</span><span style="color:#076678;">></</span><span style="font-weight:bold;color:#407959;">li</span><span style="color:#076678;">>
</span><span> {% endfor %}
</span><span style="color:#076678;"></</span><span style="font-weight:bold;color:#407959;">ul</span><span style="color:#076678;">>
</span></code></pre>
<p>{% endraw %}</p>
<p>Tujuannya agar setiap artikel muncul <code>tag</code> -nya (lihat artikel ini, dibawah Judul ada tanggal dan tag).</p>
<p>3.Nah sekarang, tinggal membuat <code>page</code> yang isinya kumpulan semua <code>tag</code>. Buatlah file dengan nama <code>tags.md</code> di folder root site kita,kemudian isi dengan:
{% raw %}</p>
<pre data-lang="html" style="background-color:#fcf0ca;color:#282828aa;" class="language-html "><code class="language-html" data-lang="html"><span>---
</span><span>layout: page
</span><span>title: Tags
</span><span>permalink: /tags/
</span><span>---
</span><span style="font-style:italic;color:#928374;"><!-- Get the tag name for every tag on the site and set them
</span><span style="font-style:italic;color:#928374;">to the `site_tags` variable. -->
</span><span>{% capture site_tags %}{% for tag in site.tags %}{{ tag | first }}{% unless forloop.last %},{% endunless %}{% endfor %}{% endcapture %}
</span><span>
</span><span style="font-style:italic;color:#928374;"><!-- `tag_words` is a sorted array of the tag names. -->
</span><span>{% assign tag_words = site_tags | split:',' | sort %}
</span><span>
</span><span style="font-style:italic;color:#928374;"><!-- List of all tags -->
</span><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">ul </span><span style="color:#407959;">class=</span><span style="color:#79740e;">"tags"</span><span style="color:#076678;">>
</span><span> {% for item in (0..site.tags.size) %}{% unless forloop.last %}
</span><span> {% capture this_word %}{{ tag_words[item] }}{% endcapture %}
</span><span> </span><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">li</span><span style="color:#076678;">>
</span><span> </span><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">a </span><span style="color:#407959;">href=</span><span style="color:#79740e;">"#{{ this_word | cgi_escape }}" </span><span style="color:#407959;">class=</span><span style="color:#79740e;">"tag"</span><span style="color:#076678;">></span><span>{{ this_word }}
</span><span> </span><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">span</span><span style="color:#076678;">></span><span>({{ site.tags[this_word].size }})</span><span style="color:#076678;"></</span><span style="font-weight:bold;color:#407959;">span</span><span style="color:#076678;">>
</span><span> </span><span style="color:#076678;"></</span><span style="font-weight:bold;color:#407959;">a</span><span style="color:#076678;">>
</span><span> </span><span style="color:#076678;"></</span><span style="font-weight:bold;color:#407959;">li</span><span style="color:#076678;">>
</span><span> {% endunless %}{% endfor %}
</span><span style="color:#076678;"></</span><span style="font-weight:bold;color:#407959;">ul</span><span style="color:#076678;">>
</span><span>---
</span><span>
</span><span>
</span><span style="font-style:italic;color:#928374;"><!-- Posts by Tag -->
</span><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">div</span><span style="color:#076678;">>
</span><span> {% for item in (0..site.tags.size) %}{% unless forloop.last %}
</span><span> {% capture this_word %}{{ tag_words[item] }}{% endcapture %}
</span><span> </span><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">h2 </span><span style="color:#79740e;">id</span><span style="color:#407959;">=</span><span style="color:#79740e;">"{{ this_word | cgi_escape }}"</span><span style="color:#076678;">></span><span>{{ this_word }}</span><span style="color:#076678;"></</span><span style="font-weight:bold;color:#407959;">h2</span><span style="color:#076678;">>
</span><span> {% for post in site.tags[this_word] %}{% if post.title != null %}
</span><span> </span><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">div</span><span style="color:#076678;">>
</span><span> </span><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">span </span><span style="color:#407959;">style=</span><span style="color:#79740e;">"</span><span style="color:#407959;">float</span><span style="color:#282828;">: </span><span style="color:#b57614;">left</span><span style="color:#282828;">;</span><span style="color:#79740e;">"</span><span style="color:#076678;">>
</span><span> </span><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">a </span><span style="color:#407959;">href=</span><span style="color:#79740e;">"{{ post.url }}"</span><span style="color:#076678;">></span><span>{{ post.title }}</span><span style="color:#076678;"></</span><span style="font-weight:bold;color:#407959;">a</span><span style="color:#076678;">>
</span><span> </span><span style="color:#076678;"></</span><span style="font-weight:bold;color:#407959;">span</span><span style="color:#076678;">>
</span><span> </span><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">span </span><span style="color:#407959;">style=</span><span style="color:#79740e;">"</span><span style="color:#407959;">float</span><span style="color:#282828;">: </span><span style="color:#b57614;">right</span><span style="color:#282828;">;</span><span style="color:#79740e;">"</span><span style="color:#076678;">>
</span><span> {{ post.date | date_to_string }}
</span><span> </span><span style="color:#076678;"></</span><span style="font-weight:bold;color:#407959;">span</span><span style="color:#076678;">>
</span><span> </span><span style="color:#076678;"></</span><span style="font-weight:bold;color:#407959;">div</span><span style="color:#076678;">>
</span><span> </span><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">div </span><span style="color:#407959;">style=</span><span style="color:#79740e;">"</span><span style="color:#407959;">clear</span><span style="color:#282828;">: </span><span style="color:#b57614;">both</span><span style="color:#282828;">;</span><span style="color:#79740e;">"</span><span style="color:#076678;">></</span><span style="font-weight:bold;color:#407959;">div</span><span style="color:#076678;">>
</span><span> {% endif %}{% endfor %}
</span><span>
</span><span> {% endunless %}{% endfor %}
</span><span>
</span><span style="color:#076678;"></</span><span style="font-weight:bold;color:#407959;">div</span><span style="color:#076678;">>
</span></code></pre>
<p>{% endraw %}</p>
<p>4.Waktunya memberi style, edit <code>main.css</code>, tambahkan:</p>
<pre data-lang="css" style="background-color:#fcf0ca;color:#282828aa;" class="language-css "><code class="language-css" data-lang="css"><span style="color:#79740e;">.tags </span><span>{
</span><span> </span><span style="color:#407959;">list-style</span><span>: </span><span style="color:#b57614;">none</span><span>;
</span><span> </span><span style="color:#407959;">margin</span><span>: </span><span style="color:#b57614;">0</span><span>;
</span><span> </span><span style="color:#407959;">overflow</span><span>: </span><span style="color:#b57614;">hidden</span><span>;
</span><span> </span><span style="color:#407959;">padding</span><span>: </span><span style="color:#b57614;">0</span><span>;
</span><span> </span><span style="color:#407959;">background</span><span>: </span><span style="color:#076678;">#fdf6e3</span><span>;
</span><span> </span><span style="color:#407959;">color</span><span>: </span><span style="color:#076678;">#2a7ae2
</span><span>}
</span><span>
</span><span style="color:#79740e;">.tags </span><span style="font-weight:bold;color:#9d0006;">li </span><span>{
</span><span> </span><span style="color:#407959;">float</span><span>: </span><span style="color:#b57614;">left</span><span>;
</span><span>}
</span><span>
</span><span style="color:#79740e;">.tag </span><span>{
</span><span> </span><span style="color:#407959;">background</span><span>: </span><span style="color:#076678;">#eee</span><span>;
</span><span> </span><span style="color:#407959;">border-radius</span><span>: </span><span style="color:#b57614;">3</span><span style="color:#8f3f71;">px </span><span style="color:#b57614;">0 0 3</span><span style="color:#8f3f71;">px</span><span>;
</span><span> </span><span style="color:#407959;">color</span><span>: </span><span style="color:#076678;">#999</span><span>;
</span><span> </span><span style="color:#407959;">display</span><span>: </span><span style="color:#b57614;">inline-block</span><span>;
</span><span> </span><span style="color:#407959;">height</span><span>: </span><span style="color:#b57614;">26</span><span style="color:#8f3f71;">px</span><span>;
</span><span> </span><span style="color:#407959;">line-height</span><span>: </span><span style="color:#b57614;">26</span><span style="color:#8f3f71;">px</span><span>;
</span><span> </span><span style="color:#407959;">padding</span><span>: </span><span style="color:#b57614;">0 20</span><span style="color:#8f3f71;">px </span><span style="color:#b57614;">0 23</span><span style="color:#8f3f71;">px</span><span>;
</span><span> </span><span style="color:#407959;">position</span><span>: </span><span style="color:#b57614;">relative</span><span>;
</span><span> </span><span style="color:#407959;">margin</span><span>: </span><span style="color:#b57614;">0 10</span><span style="color:#8f3f71;">px </span><span style="color:#b57614;">10</span><span style="color:#8f3f71;">px </span><span style="color:#b57614;">0</span><span>;
</span><span> </span><span style="color:#407959;">text-decoration</span><span>: </span><span style="color:#b57614;">none</span><span>;
</span><span> </span><span style="color:#b57614;">-webkit-</span><span style="color:#407959;">transition</span><span>: </span><span style="color:#b57614;">color 0.2</span><span style="color:#8f3f71;">s</span><span>;
</span><span>}
</span><span>
</span><span style="color:#79740e;">.tag::</span><span style="color:#407959;">before </span><span>{
</span><span> </span><span style="color:#407959;">background</span><span>: </span><span style="color:#076678;">#fff</span><span>;
</span><span> </span><span style="color:#407959;">border-radius</span><span>: </span><span style="color:#b57614;">10</span><span style="color:#8f3f71;">px</span><span>;
</span><span> </span><span style="color:#407959;">box-shadow</span><span>: </span><span style="color:#b57614;">inset 0 1</span><span style="color:#8f3f71;">px </span><span style="color:#b57614;">rgba</span><span style="color:#282828;">(</span><span style="color:#b57614;">0</span><span style="color:#282828;">, </span><span style="color:#b57614;">0</span><span style="color:#282828;">, </span><span style="color:#b57614;">0</span><span style="color:#282828;">, </span><span style="color:#b57614;">0.25</span><span style="color:#282828;">)</span><span>;
</span><span> </span><span style="color:#407959;">content</span><span>: </span><span style="color:#79740e;">''</span><span>;
</span><span> </span><span style="color:#407959;">height</span><span>: </span><span style="color:#b57614;">6</span><span style="color:#8f3f71;">px</span><span>;
</span><span> </span><span style="color:#407959;">left</span><span>: </span><span style="color:#b57614;">10</span><span style="color:#8f3f71;">px</span><span>;
</span><span> </span><span style="color:#407959;">position</span><span>: </span><span style="color:#b57614;">absolute</span><span>;
</span><span> </span><span style="color:#407959;">width</span><span>: </span><span style="color:#b57614;">6</span><span style="color:#8f3f71;">px</span><span>;
</span><span> </span><span style="color:#407959;">top</span><span>: </span><span style="color:#b57614;">10</span><span style="color:#8f3f71;">px</span><span>;
</span><span>}
</span><span>
</span><span style="color:#79740e;">.tag::</span><span style="color:#407959;">after </span><span>{
</span><span> </span><span style="color:#407959;">background</span><span>: </span><span style="color:#076678;">#fdf6e3</span><span>;
</span><span> </span><span style="color:#407959;">border-bottom</span><span>: </span><span style="color:#b57614;">13</span><span style="color:#8f3f71;">px </span><span style="color:#b57614;">solid transparent</span><span>;
</span><span> </span><span style="color:#407959;">border-left</span><span>: </span><span style="color:#b57614;">10</span><span style="color:#8f3f71;">px </span><span style="color:#b57614;">solid </span><span style="color:#076678;">#eee</span><span>;
</span><span> </span><span style="color:#407959;">border-top</span><span>: </span><span style="color:#b57614;">13</span><span style="color:#8f3f71;">px </span><span style="color:#b57614;">solid transparent</span><span>;
</span><span> </span><span style="color:#407959;">content</span><span>: </span><span style="color:#79740e;">''</span><span>;
</span><span> </span><span style="color:#407959;">position</span><span>: </span><span style="color:#b57614;">absolute</span><span>;
</span><span> </span><span style="color:#407959;">right</span><span>: </span><span style="color:#b57614;">0</span><span>;
</span><span> </span><span style="color:#407959;">top</span><span>: </span><span style="color:#b57614;">0</span><span>;
</span><span>}
</span><span>
</span><span style="color:#79740e;">.tag:</span><span style="color:#407959;">hover </span><span>{
</span><span> </span><span style="color:#407959;">background-color</span><span>: </span><span style="color:#b57614;">crimson</span><span>;
</span><span> </span><span style="color:#407959;">color</span><span>: </span><span style="color:#b57614;">white</span><span>;
</span><span> </span><span style="color:#407959;">text-decoration</span><span>: </span><span style="color:#b57614;">none</span><span>;
</span><span>}
</span><span>
</span><span style="color:#79740e;">.tag:</span><span style="color:#407959;">hover</span><span style="color:#79740e;">::</span><span style="color:#407959;">after </span><span>{
</span><span> </span><span style="color:#407959;">border-left-color</span><span>: </span><span style="color:#b57614;">crimson</span><span>;
</span><span>}
</span></code></pre>
<p>Hasilnya poin 3 dapat dilihat [disini]({{ site.url }}/tags)</p>
<p>Sudah selesai, any suggestion? feel free to [contact]({{ site.url }}/contact) me.
Thanks</p>
Membuat Tautan Referensi ke Artikel Lain dalam Jekyll
2017-05-24T11:20:47+07:00
2017-05-24T11:20:47+07:00
Unknown
https://www.sumarsono.com/membuat-tautan-referensi-ke-artikel-lain-dalam-jekyll/
<p>Ketika kita menulis artikel untuk website, ada kalanya kita akan membuat referensi ke artikel lain yang pernah kita tulis. Jekyll pun bisa melakukan hal tersebut.</p>
<p>Nah, dulu saya menggunakan cara seperti ini:
{% raw %}</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>[artikel anu]({{ site.url }}/2017/04/18/anu-ini-inu-uni/
</span></code></pre>
<p>{% endraw %}</p>
<p>Menggunakan cara seperti itu, tentu saja bisa. Namun, akan ada kendala ketika kita mengubah <code>permalink</code> situs kita.</p>
<p>Bagaimana caranya agar referensi yang kita buat bisa otomatis mengikuti <code>permalink</code> situs kita? Ternyata jekyll memiliki fitur ini. Untuk keperluan seperti itu, gunakan cara seperti ini:</p>
<p>{% raw %}</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>[artikel anu]({% post_url yyy-mm-dd-nama-artikel %})
</span></code></pre>
<p>{% endraw %}</p>
<p>Contoh:
{% raw %}</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>[artikel anu]({% post_url 2017-04-18-anu-ini-inu-uni %})
</span></code></pre>
<p>{% endraw %}</p>
<p>Nantinya, kode <code>html</code> yang dihasilkan akan mengikuti <code>permalink</code> situs kita.</p>
<p>Sekian</p>
Memasang Wall Facelet CAT5e Panasonic
2017-05-22T07:29:26+07:00
2017-05-22T07:29:26+07:00
Unknown
https://www.sumarsono.com/memasang-wall-facelet-cat5e-panasonic/
<p>Saya belajar cara memasang konektor <em>wall facelet CAT5e</em> sudah sangat lama, yakni ketika duduk dibangku SMK. Setelah sekian lama, baru hari ini ilmu itu saya terapkan dalam bentuk <em>nyata</em> bukan sekedar latihan.</p>
<p>Hari ini, saya memasang <em>wall facelet CAT5e</em> merk Panasonic. Tujuan pemasangannya adalah biar instalasi kabel LAN bisa rapi.</p>
<p>Biasanya, dalam memasang kabel LAN semacam ini kita butuh <em>D Impact tool</em>, atau ada yang menyebutnya <em>cable knock down tool</em>.</p>
<p>Nah, kalau si Panasonic ini gak usah repot, karena penutupnya di desain untuk menggantikan tool tadi, jadi cukup tempatkan kabel sesuai warnanya, kemudian tekan pakai penutupnya sampai ada punyi "krek".</p>
<p>Selesai, tinggal dipasang ke <em>outbow</em> atau <em>inbow</em>.</p>
<p>Penampakan:</p>
<p><img src="/assets/images/wall-facelet-cat5e-panasonic.webp" alt="wall facelet Panasonic" /></p>
<p><img src="/assets/images/outbow-panasonic.webp" alt="outbow Panasonic" /></p>
<p><img src="/assets/images/tes-cat5e-panasonic.webp" alt="tes CAT5e Panasonic" /></p>
Atom, Powerfull Markdown Editor di Fedora 25
2017-05-20T22:15:50+07:00
2017-05-20T22:15:50+07:00
Unknown
https://www.sumarsono.com/atom-powerfull-markdown-editor-di-fedora-25/
<p>Dulu, kali pertama mencoba Atom sewaktu awal-awal rilis. Rasanya tidak enak jika dibandingkan text editor lainnya.
Setelah sekian lama, akhirnya hari ini saya unduh Atom dan mencoba lagi, beda sekali rasanya, sekarang lebih <em>smoot</em>.</p>
<p>Alasan kenapa hari ini mencoba Atom adalah untuk mencoba menggunakannya debagai <code>Markdown</code> editor. Ternyata lumayan ciamik. Fitur yang saya suka adalah <code>markdown preview</code>, jadi bisa melihat langsung hasil <code>markdown</code> yang kita tulis.</p>
<p>Untuk mengaktifkan fitur tersebut cukup klik <strong>Packages > Markdown Preview > Toggle Preview</strong> atau dengan shortcut <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>M</kbd></p>
<p>Berikut ini skriksutnya:</p>
<p><img src="/assets/images/ss-atom-markdown.webp" alt="Atom Markdown" /></p>
<p>Keren kan?? :+1:</p>
Flash boot Android Menggunakan Fastboot
2017-05-20T15:56:26+07:00
2017-05-20T15:56:26+07:00
Unknown
https://www.sumarsono.com/flash-boot-android-menggunakan-fastboot/
<p>Melanjutkan artikel [membongkar boot.img]({% post_url 2017-05-20-bongkar-boot.img-android-di-fedora-25 %})</p>
<p>Sekarang akan saya bahas cara flash file <code>new-boot.img</code> yang telah dibuat, metode yang saya pakai adalah menggunakan <code>fastboot</code> karena sangat mudah.</p>
<ol>
<li>Aktifkan <code>usb debugging</code> di hp</li>
<li>Tancapkan ke laptop</li>
<li>Buka Terminal</li>
<li><code>cd</code> ke lokasi new-boot.img</li>
<li>reboot HP ke mode <code>fastboot</code></li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>adb reboot-bootloader
</span></code></pre>
<ol start="6">
<li>Setelah muncul tulisan fastboot di layar HP, jalankan perintah ini:</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>fastboot flash boot new-boot.img
</span></code></pre>
<p>Hanya butuh beberapa detik untuk selesai
7. Reboot HP</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>fastboot reboot
</span></code></pre>
<p>Selamat, sekarang <code>/system</code> sudah termount dalam mode <code>rw</code></p>
<p>:+1:</p>
Bongkar boot.img Android di Fedora 25
2017-05-20T15:16:24+07:00
2017-05-20T15:16:24+07:00
Unknown
https://www.sumarsono.com/bongkar-boot-img-android-di-fedora-25/
<p>Hari ini saya mendapati custom ROM Android yang <code>/system</code> nya termount <code>ro</code> atau <em>read only</em>. Padahal saya mau edit file [ini]({% post_url 2017-05-20-disable-tombol-kapasitip-hp-android-rom-cm13-google-seed %}) di <code>system</code>.</p>
<p>Usut punya usut, agar <code>/system</code> termount dalam mode <code>rw</code> harus bongkar <code>boot.img</code>. Untungnya sudah ada yang membuat <code>bash script</code> untuk <em>unpack</em> dan <em>repack</em> <code>boot.img</code></p>
<ol>
<li>Unduh <a href="https://github.com/GameTheory-/mktool.git">disini</a> lalu ekstrak</li>
<li>Copy paste file boot.img ke dalam folder mktool</li>
<li>jalankan ./mktool
<img src="/assets/images/ss-mktool.webp" alt="Fedora_winten" /></li>
<li>Pilih <strong>2</strong> dan masukan nama file boot.img nya.</li>
<li>Edit file <code>/mktool/extracted/ramdisk/fstab.qcom</code></li>
<li>Ubah baris:
bash-script
/dev/block/bootdevice/by-name/system /system ext4 ro,barrier=1 wait</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>menjadi:
</span><span>bash-script
</span><span>/dev/block/bootdevice/by-name/system /system ext4 rw,barrier=1 wait
</span></code></pre>
<ol start="7">
<li>Simpan</li>
<li>kembali ke jendela mktool, pilih repack. Nanti akan menghasilkan file <code>new-boot.img</code></li>
<li>File tersebut siap di flash via fastboot flash</li>
</ol>
<p>Selesai.
Next time, kita bahas cara flash file tadi pakai fastboot :+1:</p>
<p>Update: Sudah saya tulis cara flash-nya klik tombol <code>next</code> dibawah post ini :laughing:</p>
Disable Tombol Kapasitip HP Android ROM CM13 Google Seed
2017-05-20T15:00:10+07:00
2017-05-20T15:00:10+07:00
Unknown
https://www.sumarsono.com/disable-tombol-kapasitip-hp-android-rom-cm13-google-seed/
<p>Bosan menggunakan tombol fisik? ingin ganti ke softkey? sudah ganti tapi tombol fisik terasa <em>annoying</em>?</p>
<p>Mudah saja. Disable aja tombol kapasitipnya.
Caranya? check this out:</p>
<ol>
<li>Hubungkan HP ke Laptop</li>
<li>Aktifkan <code>USB Debugging</code> di HP</li>
<li>Buka Termninal</li>
<li>Jalankan perintah adb shell dan minta hak ases <code>root</code>:
bash
adb shell
su</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>5. Edit file `Generic.kl`:
</span><span>bash
</span><span>vim /system/usr/keylayout/Generic.kl
</span></code></pre>
<ol start="6">
<li>
<p>Cari tulisan:</p>
<ul>
<li><code>key 139 MENU</code></li>
<li><code>key 172 HOME</code></li>
<li><code>key 158 BACK</code></li>
</ul>
<p>Kemudian beri tanda <code>#</code> didepannya</p>
</li>
<li>
<p>Simpan</p>
</li>
<li>
<p>Exit adb shell</p>
</li>
<li>
<p>Reboot HP
bash
adb reboot</p>
</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code></code></pre>
Fedora ala ala Winten
2017-05-18T06:18:04+07:00
2017-05-18T06:18:04+07:00
Unknown
https://www.sumarsono.com/fedora-ala-ala-winten/
<p>Jenuh dengan tampilan Fedora yang default (Gnome3)? Saya, pagi ini tidak sengaja nemu artikel di omgubuntu yang membahas <code>gnome-layout-manager</code>.</p>
<p>Nah, gnome layout manager ini, merupakan skrip yang dibuat oleh <strong>bill mavromatis</strong> untuk mengubah layout gnome3. Skrip ini menawarkan 3 layout: Windows 10, Ubuntu Unity, dan MacOS.</p>
<p>Penasaran, saya coba download skripnya <a href="https://github.com/bill-mavromatis/gnome-layout-manager/">disini</a>{: target="_blank"}. Dan mengikuti panduan yang ada disana.</p>
<p>Nah, ini hasilnya:
<img src="/assets/images/ss-fedora-winten.webp" alt="Fedora_winten" /></p>
Membeli Nokia 150
2017-05-17T07:27:04+07:00
2017-05-17T07:27:04+07:00
Unknown
https://www.sumarsono.com/membeli-nokia-150/
<p>Beberapa waktu yang lalu, saya ingin beli <em>featured phone</em>. Tujuan saya beli jenis hp ini adalah untuk saya tinggal dirumah agar dipakai emak. Emak saya tidak bisa baca tulis, tapi bisa diajari untuk menerima panggilan telepon.</p>
<p>Setelah <em>browsing</em>, featured phone murah-murah harganya, harga terendah yang saya dapati 90rb. Sebelumnya, pernah beli harga 100rb merk X, sudah rusak.</p>
<p>Akhirnya saya putuskan untuk beli Nokia 150 seharga 370rb. Dalam hati bertanya-tanya, apakah Nokia masih sebandel (dalam artian awet) dulu?.</p>
<p>Setelah unboxing, saya dapati unit HP made in Vietnam, Headset made in Vietnam, dan Charger made in India. Dan kartu garansi serta buku manual. Nah disana didapati bahwa merk dagang nokia untuk <em>low cost phone</em> sudah diambil alih oleh <strong>HMD GLOBAL</strong>, semua yang ada di dalam dus adalah produksi <strong>HMD GLOBAL</strong> dan dipasarkan dengan merk Nokia.</p>
<p>HP-nya sih ringan, kelihatan ringkih, chargernya juga. Kabel charger terlihat tidak meyakinkan :laughing:</p>
<p>Tapi baterai lumayan kuat semingguan untuk aktifitas nerima telepon yang tidak terlalu sering. <em>Charge</em> penuh dalam waktu 1 jam 30 menit saja. Suara juga jernih, loudpeaker oke, LCD lumayan bening dibandingkan <em>featured phone</em> yang sebelumnya. Kamera hanya pajangan saja, hasilnya ya alakadarnya :laughing:</p>
<p>Nah, yang saya kaget, HP ini tidak bisa buat browsing :laughing: beda dengan Nokia yang dulu. Game ada 2, ular-ularan sama balap mobil, yang balap mobil harus beli seharga 15rb.</p>
<p>Semoga HP-nya awet, jadi bisa tetap komunikasi sama emak di kampung.</p>
<p>Sekian</p>
Menjaga Versi Kernel Tertentu Supaya Tidak Terhapus Ketika Update Fedora
2017-05-16T12:21:04+07:00
2017-05-16T12:21:04+07:00
Unknown
https://www.sumarsono.com/menjaga-versi-kernel-tertentu-agar-tidak-terhapus-ketika-update-fedora/
<p>Secara default, Fedora 25 akan menjaga 3 versi kernel di mesin kita. Ketika ada pembaruan versi kernel, maka versi kernel terendah akan terhapus.</p>
<p>Ada kalanya karena suatu keperluan, kita perlu menjaga suatu versi kernel tertentu agar tidak terhapus ketika melakukan <code>dnf update</code>. Berikut ini caranya:</p>
<ol>
<li>Kita list dulu daftar kernel yang terpasang di mesin kita, dari terminal kita jalankan:</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>rpm -qa kernel
</span></code></pre>
<p>Nah, nanti akan keluar daftar kernel yang terpasang, contohnya di saya:
bash
kernel-4.10.14-200.fc25.x86_64
kernel-4.10.12-200.fc25.x86_64
kernel-4.10.13-200.fc25.x86_64</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>`-qa` == `-q` untuk `query` dan `-a` untuk `all` artinya query all kernel
</span><span>2. Misalnya kita butuh `kernel-4.10.13-200.fc25.x86_64` agar tidak terhapus, jalankan perintah berikut:
</span></code></pre>
<p>sudo dnf mark install kernel-4.10.13-200.fc25.x86_64</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>apa itu `dnf mark`? berikut ini dari man page-nya:
</span><span>bash
</span><span>dnf mark install <package-specs>...
</span><span> Marks the specified packages as installed by user. This can be useful if any package was installed as a dependency and is desired to
</span><span> stay on the system when Auto Remove Command or Remove Command along with clean_requirements_on_remove configuration option set to
</span><span> True is executed.
</span></code></pre>
<p>Nah, sekian dulu.</p>
Mencoba Oh My Zsh
2017-05-07T20:06:04+07:00
2017-05-07T20:06:04+07:00
Unknown
https://www.sumarsono.com/mencoba-oh-my-zsh/
<p>Melanjutkan tulisan tentang <code>zsh</code> [disini]({% post_url 2017-05-07-mencoba-zsh-di-fedora-25 %}). Jika teman-teman mengikuti artikel tersebut, pasti tampilan <code>zsh</code> -nya biasa-biasa aja. Nah, pada artikel ini akan saya sampaikan bagaimana agar shell <code>zsh</code> jadi cantik.</p>
<p>Caranya adalah dengan memasang <code>oh-my-zsh</code>. Simple aja, eksekusi <em>command</em> berikut di terminal:</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>wget --no-check-certificate http://install.ohmyz.sh -O - | sh
</span></code></pre>
<p>Nah untuk mengganti tema, cukup edit file <code>.zshrc</code> di /home.</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>nano ~/.zshrc
</span></code></pre>
<p>Cari baris</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span># See https://github.com/robbyrussell/oh-my-zsh/wiki/Themes
</span><span>ZSH_THEME="robbyrussell"
</span></code></pre>
<p>Kemudian ganti robbyrussell dengan tema lain, misalnya :</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>ZSH_THEME="agnoster"
</span></code></pre>
<p>Selesai</p>
Mencoba ZSH di Fedora 25
2017-05-07T19:12:25+07:00
2017-05-07T19:12:25+07:00
Unknown
https://www.sumarsono.com/mencoba-zsh-di-fedora-25/
<p>Berawal dari perbincangan di group telegram, Saya jadi ingin mencoba (lagi) <code>ZSH</code> untuk menggantikan <code>BASH</code>. Salah satu yang saya suka dari ZSH adalah tampilannya yang menarik, ditambah lagi dengan adanya <code>Oh My Zsh</code>.</p>
<p>Mengganti BASH dengan ZSH di Fedora 25 terbilang cukup mudah, berikut ini caranya:</p>
<ol>
<li>Install paket <code>zsh</code> dan <code>util-linux-user</code>. Dari <code>util-linux-user</code> kita butuh <code>chsh</code> untuk me-replace bash dengan zsh.</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>sudo dnf install zsh util-linux-user
</span></code></pre>
<ol start="2">
<li>Ganti bash menjadi zsh dengan cara:</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>chsh -s /usr/bin/zsh
</span></code></pre>
<ol start="3">
<li>Tutup terminal dan buka lagi, <code>bash</code> sudah tergantikan oleh <code>zsh</code></li>
</ol>
<p>Nah, next time kita bahas <code>oh my zsh</code>.</p>
Memperbaiki Touchpad Error di Fedora
2017-04-27T20:44:40+07:00
2017-04-27T20:44:40+07:00
Unknown
https://www.sumarsono.com/memperbaiki-touchpad-error-di-fedora/
<p>Beberapa waktu yang lalu, saya jenuh dengan <strong>GNOME</strong>. Oleh sebab itu saya memasang <strong>PLASMA</strong>.
Namun apa daya, itu hanya pelarian sesaat. Akhirnya saya memutuskan untuk membuang plasma dan kembali ke gnome.</p>
<p>Proses balikan ini tidak berjalan mulus, setelah saya remove plasma kemudian set <code>gdm</code> over <code>sddm</code> kemudian reboot, startx gagal start. Hal ini disebabkan karena komponen gnome ada yang hilang terbawa plasma yang saya buang. Okelah tidak apa-apa, saya install gnome lagi. Kemudian reboot dan jreng masuk ke Desktop. Senangnya, bisa balikan ke gnome.</p>
<p>Namun ternyata, cobaan untuk balikan masih ada. Semua lancar ketika di <code>wayland</code> session, namun karena saya belum sreg, saya switch ke <code>Xorg</code> session. Disini masalah muncul lagi, Touchpadnya hanya bisa klik kanan dan klik kiri, tidak bisa move kursor. <em>WTF</em> dalam hati.</p>
<p>Sudah pusing, saya putuskan cari solusi di pegelinux. Disana, disarankan untuk memasang <code>Xorg-libinput</code> karena diduga paket itu belum terpasang. Hmmm masuk akal, oke saya pasang di fedora dengan cara:
bash
sudo dnf install xorg-x11-drv-libinput</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>
</span><span>dan jreng, bisa. Wow, awesome. :laughing:
</span><span>
</span><span>Terima kasih pegelinux..... :+1:</span></code></pre>
Menambah Tombol Navigasi Next Archive Previous di Jekyll bagian II
2017-04-25T09:08:23+07:00
2017-04-25T09:08:23+07:00
Unknown
https://www.sumarsono.com/menambah-tombol-navigasi-next-archive-previous-di-jekyll-bagian-ii/
<p>Pada artikel [sebelumnya]({% post_url 2017-04-18-menambah-tombol-navigasi-next-archive-previous-di-jekyll %}), sudah ditulis caranya. Namun, saya kurang puas dengan hasilnya.</p>
<p>Nah, suatu ketika saya berkunjung ke blog teman, navigasinya bagus eui.. bentuknya tombol. Kemudian saya putuskan untuk meniru dari blog teman saya. Berikut ini source code nya:
{% raw %}</p>
<pre data-lang="html" style="background-color:#fcf0ca;color:#282828aa;" class="language-html "><code class="language-html" data-lang="html"><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">div </span><span style="color:#407959;">class=</span><span style="color:#79740e;">"page-navigation"</span><span style="color:#076678;">>
</span><span> </span><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">ul</span><span style="color:#076678;">>
</span><span> {% if page.previous %}
</span><span> </span><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">li </span><span style="color:#407959;">class=</span><span style="color:#79740e;">"previous"</span><span style="color:#076678;">><</span><span style="font-weight:bold;color:#407959;">a </span><span style="color:#407959;">href=</span><span style="color:#79740e;">"{{page.previous.url}}" </span><span style="color:#407959;">title=</span><span style="color:#79740e;">"{{ page.previous.title }}"</span><span style="color:#076678;">></span><span style="color:#8f3f71;">&larr;</span><span> Previous</span><span style="color:#076678;"></</span><span style="font-weight:bold;color:#407959;">a</span><span style="color:#076678;">></</span><span style="font-weight:bold;color:#407959;">li</span><span style="color:#076678;">>
</span><span> {% else %}
</span><span> </span><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">li </span><span style="color:#407959;">class=</span><span style="color:#79740e;">"previous disabled"</span><span style="color:#076678;">><</span><span style="font-weight:bold;color:#407959;">a</span><span style="color:#076678;">></span><span style="color:#8f3f71;">&larr;</span><span> Previous</span><span style="color:#076678;"></</span><span style="font-weight:bold;color:#407959;">a</span><span style="color:#076678;">></</span><span style="font-weight:bold;color:#407959;">li</span><span style="color:#076678;">>
</span><span> {% endif %}
</span><span> </span><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">li</span><span style="color:#076678;">><</span><span style="font-weight:bold;color:#407959;">a </span><span style="color:#407959;">href=</span><span style="color:#79740e;">"{{site.baseurl}}/archive/"</span><span style="color:#076678;">></span><span>Archive</span><span style="color:#076678;"></</span><span style="font-weight:bold;color:#407959;">a</span><span style="color:#076678;">></</span><span style="font-weight:bold;color:#407959;">li</span><span style="color:#076678;">>
</span><span> {% if page.next %}
</span><span> </span><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">li </span><span style="color:#407959;">class=</span><span style="color:#79740e;">"next"</span><span style="color:#076678;">><</span><span style="font-weight:bold;color:#407959;">a </span><span style="color:#407959;">href=</span><span style="color:#79740e;">"{{page.next.url}}" </span><span style="color:#407959;">title=</span><span style="color:#79740e;">"{{ page.next.title }}"</span><span style="color:#076678;">></span><span>Next </span><span style="color:#8f3f71;">&rarr;</span><span style="color:#076678;"></</span><span style="font-weight:bold;color:#407959;">a</span><span style="color:#076678;">></</span><span style="font-weight:bold;color:#407959;">li</span><span style="color:#076678;">>
</span><span> {% else %}
</span><span> </span><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">li </span><span style="color:#407959;">class=</span><span style="color:#79740e;">"next disabled"</span><span style="color:#076678;">><</span><span style="font-weight:bold;color:#407959;">a</span><span style="color:#076678;">></span><span>Next </span><span style="color:#8f3f71;">&rarr;</span><span style="color:#076678;"></</span><span style="font-weight:bold;color:#407959;">a</span><span style="color:#076678;">>
</span><span> {% endif %}
</span><span> </span><span style="color:#076678;"></</span><span style="font-weight:bold;color:#407959;">ul</span><span style="color:#076678;">>
</span><span> </span><span style="color:#076678;"></</span><span style="font-weight:bold;color:#407959;">div</span><span style="color:#076678;">>
</span></code></pre>
<p>{% endraw %}</p>
<p>nah berikut ini kode 'css' biar jadi cantik
{% raw %}</p>
<pre data-lang="css" style="background-color:#fcf0ca;color:#282828aa;" class="language-css "><code class="language-css" data-lang="css"><span style="color:#79740e;">.page-navigation </span><span>{
</span><span> </span><span style="color:#407959;">height</span><span>:</span><span style="color:#b57614;">20</span><span style="color:#8f3f71;">px</span><span>;
</span><span> </span><span style="color:#407959;">margin</span><span>:</span><span style="color:#b57614;">18</span><span style="color:#8f3f71;">px </span><span style="color:#b57614;">0</span><span>;
</span><span> </span><span style="color:#407959;">display</span><span>: </span><span style="color:#b57614;">block</span><span>;
</span><span> </span><span style="color:#407959;">text-align</span><span>: </span><span style="color:#b57614;">center</span><span>;
</span><span>}
</span><span style="color:#79740e;">.page-navigation </span><span style="font-weight:bold;color:#9d0006;">ul </span><span>{
</span><span> </span><span style="color:#407959;">padding</span><span>:</span><span style="color:#b57614;">0</span><span>;
</span><span> </span><span style="color:#407959;">display</span><span>: </span><span style="color:#b57614;">inline-block</span><span>;
</span><span> </span><span style="color:#407959;">margin</span><span>:</span><span style="color:#b57614;">0</span><span>;
</span><span> </span><span style="color:#407959;">border</span><span>:</span><span style="color:#b57614;">1</span><span style="color:#8f3f71;">px </span><span style="color:#b57614;">solid </span><span style="color:#076678;">#ddd</span><span>;
</span><span> </span><span style="color:#407959;">border</span><span>:</span><span style="color:#b57614;">1</span><span style="color:#8f3f71;">px </span><span style="color:#b57614;">solid rgba</span><span style="color:#282828;">(</span><span style="color:#b57614;">0</span><span style="color:#282828;">,</span><span style="color:#b57614;">0</span><span style="color:#282828;">,</span><span style="color:#b57614;">0</span><span style="color:#282828;">,</span><span style="color:#b57614;">0.15</span><span style="color:#282828;">)</span><span>;
</span><span> </span><span style="color:#407959;">border-radius</span><span>:</span><span style="color:#b57614;">3</span><span style="color:#8f3f71;">px</span><span>;
</span><span> </span><span style="color:#407959;">box-shadow</span><span>:</span><span style="color:#b57614;">0 1</span><span style="color:#8f3f71;">px </span><span style="color:#b57614;">2</span><span style="color:#8f3f71;">px </span><span style="color:#b57614;">rgba</span><span style="color:#282828;">(</span><span style="color:#b57614;">0</span><span style="color:#282828;">,</span><span style="color:#b57614;">0</span><span style="color:#282828;">,</span><span style="color:#b57614;">0</span><span style="color:#282828;">,</span><span style="color:#b57614;">0.05</span><span style="color:#282828;">)</span><span>;
</span><span> </span><span style="color:#407959;">text-align</span><span>: </span><span style="color:#b57614;">center</span><span>;
</span><span>
</span><span>}
</span><span>
</span><span style="color:#79740e;">.page-navigation </span><span style="font-weight:bold;color:#9d0006;">li </span><span>{
</span><span> </span><span style="color:#407959;">display</span><span>:</span><span style="color:#b57614;">inline
</span><span>}
</span><span style="color:#79740e;">.page-navigation </span><span style="font-weight:bold;color:#9d0006;">a </span><span>{
</span><span> </span><span style="color:#407959;">float</span><span>:</span><span style="color:#b57614;">left</span><span>;
</span><span> </span><span style="color:#407959;">padding</span><span>:</span><span style="color:#b57614;">0 14</span><span style="color:#8f3f71;">px</span><span>;
</span><span> </span><span style="color:#407959;">line-height</span><span>:</span><span style="color:#b57614;">34</span><span style="color:#8f3f71;">px</span><span>;
</span><span> </span><span style="color:#407959;">border-right</span><span>:</span><span style="color:#b57614;">1</span><span style="color:#8f3f71;">px </span><span style="color:#b57614;">solid</span><span>;
</span><span> </span><span style="color:#407959;">border-right-color</span><span>:</span><span style="color:#076678;">#ddd</span><span>;
</span><span> </span><span style="color:#407959;">border-right-color</span><span>:</span><span style="color:#b57614;">rgba</span><span style="color:#282828;">(</span><span style="color:#b57614;">0</span><span style="color:#282828;">,</span><span style="color:#b57614;">0</span><span style="color:#282828;">,</span><span style="color:#b57614;">0</span><span style="color:#282828;">,</span><span style="color:#b57614;">.15</span><span style="color:#282828;">)
</span><span>}
</span><span style="color:#79740e;">.page-navigation </span><span style="font-weight:bold;color:#9d0006;">a</span><span style="color:#79740e;">:</span><span style="color:#407959;">hover </span><span>{
</span><span> </span><span style="color:#407959;">background-color</span><span>:</span><span style="color:#076678;">#eee
</span><span>}
</span><span style="color:#79740e;">.page-navigation .disabled </span><span style="font-weight:bold;color:#9d0006;">a</span><span style="color:#79740e;">,.page-navigation .disabled </span><span style="font-weight:bold;color:#9d0006;">a</span><span style="color:#79740e;">:</span><span style="color:#407959;">hover </span><span>{
</span><span> </span><span style="color:#407959;">background-color</span><span>:</span><span style="color:#b57614;">transparent</span><span>;
</span><span> </span><span style="color:#407959;">color</span><span>:</span><span style="color:#076678;">#968896
</span><span>}
</span><span style="color:#79740e;">.page-navigation .next </span><span style="font-weight:bold;color:#9d0006;">a </span><span>{
</span><span> </span><span style="color:#407959;">border</span><span>:</span><span style="color:#b57614;">0
</span><span>}
</span></code></pre>
<p>{% endraw %}</p>
<p>Hasilnya, seperti yang anda lihat di bawah post ini. :+1:</p>
Menambah tombol navigasi next archive previous di jekyll
2017-04-18T08:03:23+07:00
2017-04-18T08:03:23+07:00
Unknown
https://www.sumarsono.com/menambah-tombol-navigasi-next-archive-previous-di-jekyll/
<p>Beberapa hari ini, saya mainan <em>static site</em> dengan memanfaatkan jekyll dan gh-page.</p>
<p>Nah hari ini, setelah saya lihat-lihat <em>static site</em> saya ada yang kurang. Dulu pas main wordpress ada yang namanya <em>next post</em> sama <em>previous post</em>.</p>
<p>Oleh karena itu, hari ini saya menambahkan fitur itu.</p>
<h2 id="check-this-out">Check this out</h2>
<ol>
<li>
<p>edit <code>_layouts/post.html</code> . Tambahkan sebelum <code></article></code> biar lokasinya ada dibawah konten utama:
{% raw %}</p>
<pre data-lang="html" style="background-color:#fcf0ca;color:#282828aa;" class="language-html "><code class="language-html" data-lang="html"><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">div </span><span style="color:#407959;">class=</span><span style="color:#79740e;">"PageNavigation"</span><span style="color:#076678;">>
</span><span> {% if page.previous.url %}
</span><span> </span><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">a </span><span style="color:#407959;">class=</span><span style="color:#79740e;">"prev" </span><span style="color:#407959;">href=</span><span style="color:#79740e;">"{{page.previous.url}}"</span><span style="color:#076678;">></span><span> « {{page.previous.title}}</span><span style="color:#076678;"></</span><span style="font-weight:bold;color:#407959;">a</span><span style="color:#076678;">>
</span><span> {% endif %}
</span><span>
</span><span> {% if page.next.url %}
</span><span> </span><span style="color:#076678;"><</span><span style="font-weight:bold;color:#407959;">a </span><span style="color:#407959;">class=</span><span style="color:#79740e;">"next" </span><span style="color:#407959;">href=</span><span style="color:#79740e;">"{{page.next.url}}"</span><span style="color:#076678;">></span><span> {{page.next.title}} »</span><span style="color:#076678;"></</span><span style="font-weight:bold;color:#407959;">a</span><span style="color:#076678;">>
</span><span> {% endif %}
</span><span style="color:#076678;"></</span><span style="font-weight:bold;color:#407959;">div</span><span style="color:#076678;">>
</span></code></pre>
<p>{% endraw %}</p>
</li>
<li>
<p>edit <code>css</code> . Tambahkan:
{% raw %}</p>
<pre data-lang="css" style="background-color:#fcf0ca;color:#282828aa;" class="language-css "><code class="language-css" data-lang="css"><span> </span><span style="color:#79740e;">.PageNavigation </span><span>{
</span><span> </span><span style="color:#407959;">font-size</span><span>: </span><span style="color:#b57614;">16</span><span style="color:#8f3f71;">px</span><span>;
</span><span> </span><span style="color:#407959;">display</span><span>: </span><span style="color:#b57614;">block</span><span>;
</span><span> </span><span style="color:#407959;">width</span><span>: </span><span style="color:#b57614;">auto</span><span>;
</span><span> </span><span style="color:#407959;">overflow</span><span>: </span><span style="color:#b57614;">hidden</span><span>;
</span><span> }
</span><span>
</span><span style="color:#79740e;">.PageNavigation </span><span style="font-weight:bold;color:#9d0006;">a </span><span>{
</span><span> </span><span style="color:#407959;">display</span><span>: </span><span style="color:#b57614;">block</span><span>;
</span><span> </span><span style="color:#407959;">width</span><span>: </span><span style="color:#b57614;">50</span><span style="color:#8f3f71;">%</span><span>;
</span><span> </span><span style="color:#407959;">float</span><span>: </span><span style="color:#b57614;">left</span><span>;
</span><span> </span><span style="color:#407959;">margin</span><span>: </span><span style="color:#b57614;">1</span><span style="color:#8f3f71;">em </span><span style="color:#b57614;">0</span><span>;
</span><span> }
</span><span>
</span><span style="color:#79740e;">.PageNavigation .next </span><span>{
</span><span> </span><span style="color:#407959;">text-align</span><span>: </span><span style="color:#b57614;">right</span><span>;
</span><span> }
</span></code></pre>
<p>{% endraw %}</p>
</li>
</ol>
<p>Selesai</p>
<hr>
memperbaiki tampilan emoji di gh-page
2017-04-17T15:52:42+07:00
2017-04-17T15:52:42+07:00
Unknown
https://www.sumarsono.com/memperbaiki-tampilan-emoji-di-gh-page/
<p>Setelah berhasil memasang [jemoji]({% post_url 2017-04-17-menambah-emoji-di-gh-page %}) , ternyata ada kendala, tampilan emojinya terlalu <strong>GEDE</strong> :laughing:</p>
<p>Akhirnya saya tanyakan ke group pegelinux, disana dapat solasi :laughing:. Disarankan untuk mengatur ukurannya via <code>css</code>.</p>
<p>Akhirnya saya tambahkan di file <code>css</code>:</p>
<pre data-lang="css" style="background-color:#fcf0ca;color:#282828aa;" class="language-css "><code class="language-css" data-lang="css"><span style="color:#79740e;">emoji </span><span>{
</span><span> </span><span style="color:#407959;">display</span><span>: </span><span style="color:#b57614;">inline-block</span><span>;
</span><span> </span><span style="color:#407959;">height</span><span>: </span><span style="color:#b57614;">1</span><span style="color:#8f3f71;">em</span><span>;
</span><span> </span><span style="color:#407959;">width</span><span>: </span><span style="color:#b57614;">auto</span><span>;
</span><span>}
</span></code></pre>
<p>contoh penggunaanya di post:
<code>:+1:</code> nanti jadi :+1:</p>
<p>dan tara...selesai, emoji tampil dengan normal, :+1:</p>
Menambah Emoji di gh-pages
2017-04-17T12:08:00+07:00
2017-04-17T12:08:00+07:00
Unknown
https://www.sumarsono.com/menambah-emoji-di-gh-page/
<p>Sebenarnya ini iseng aja, :laughing: Biar static page punya saya <em>kece</em> saya menambah emoji kesini.</p>
<p>Nah, saya tulis saja pengalaman itu kesini, biar blog ini ada isinya.</p>
<h2 id="check-this-out">Check this out</h2>
<p>Untuk menambah emoji kita akan memanfaatkan <strong>jemoji</strong> , nah yang pertama harus dilakukan adalah edit file <code>_config.yml</code> :
{% highlight raw %}
gems:
- jemoji
{% endhighlight %}</p>
<p>Next, push ke repo gh-pages kita. Dan coba bikin emoji post kita misalnya emoji ketawa <code>:laughing:</code></p>
<p>Profit.</p>
Menjalankan tg-cli di raspberry pi 3
2017-04-16T17:44:00+07:00
2017-04-16T17:44:00+07:00
Unknown
https://www.sumarsono.com/menjalankan-tg-cli-di-raspberry-pi-3/
<p>Telegram, platform chat yang cukup populer. Ada yang menarik dari telegram ini, yaitu tersedia telegram cli (ce el i ya bukan coli) yang selanjutnya kita sebut tg-cli.</p>
<p>Nah, saya bermaksud membuat bot telegram menggunakan tg-cli yang akan run di raspi 3. So langkah pertama untuk keinginan saya tsb adalah bagaimana menjalankan tg-cli raspberry pi 3.</p>
<p>Sebenarnya, di laman repo tg-cli yaitu https://github.com/vysheng/tg.git sudah dijelaskan bagaimana cara untuk kompilasi tg-cli sesuai dengan OS yang kita gunakan. Tapi eh tapi tadi waktu saya praktekan, ada kendala error <code>Can not connect (tgl/mtproto-utils.c:101: BN2ull: Assertion </code>0' failed)`. Jadi saya tulis ulang aja disini beserta cara fix-nya.</p>
<h2 id="you-will-need">You will need</h2>
<p><strong>Working internet connection</strong> :laughing:</p>
<h2 id="check-this-out">Check this out</h2>
<ol>
<li>of course <code>ssh</code> ke raspberry pi 3 kamu.</li>
<li>clone repo tg-cli ke raspberry pi 3.
bash
git clone --recursive https://github.com/vysheng/tg.git</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>3. Pindah ke direktori hasil clone tadi
</span><span>bash
</span><span>cd tg
</span></code></pre>
<ol start="4">
<li>Edit file <code>tg/tgl/mtproto-utils.c</code> untuk ngatasin error yang tadi saya sebutkan
bash
nano tgl/mtproto-utils.c</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>Cari `assert (0); // As long as nobody ever uses this code, assume` yang berada pada **line 101 dan 115** , comment kedua baris tsb.
</span><span>
</span><span>5. Pasang dependensi yang dibutuhkan
</span><span>bash
</span><span>sudo apt-get install libreadline-dev libconfig-dev libssl-dev lua5.2 liblua5.2-dev libevent-dev libjansson-dev libpython-dev make
</span></code></pre>
<ol start="6">
<li>Jalankan perintah berikut ini:
bash
./configure
make</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>7. Kalau sudah selesai, coba jalankan tg-cli
</span><span>bash
</span><span>bin/telegram-cli -k tg/tg-server.pub -W
</span></code></pre>
<ol start="8">
<li>Masukan nomor HP dan tara....selesai. Tg-cli siap digunakan.</li>
</ol>
<p>Nah itu tadi tentang apa yang saya lakukan, jangan tanya kenapa kok gini kenapa kok gitu, ini maksudnya apa, dst. Karena saya tidak mudeng. wkwkwk</p>
Raspberry pi 3 Headless Mode
2017-04-14T21:21:00+07:00
2017-04-14T21:21:00+07:00
Unknown
https://www.sumarsono.com/raspberry-pi-3-headless/
<p>Yo...bicara soal raspi 3 lagi. Dalam menggunakan raspi 3 mestinya membutuhkan perangkat tambahan untuk konfigurasi, minimal keyboard dan monitor.
Bagaimana kalau kita tidak punya keduanya? pusing. Haha. Tenang, akan saya tulis bagaimana mengkonfigurasi raspi 3 meskipun tidak punya monitor sama keyboard untuk dipasang di raspi 3.</p>
<p>Nah, pada artikel ini akan saya share:</p>
<ol>
<li>Install Raspbian Lite.</li>
<li>Mengakses raspi 3 meskipun tidak punya monitor dan keyboard untuk raspi.</li>
</ol>
<p>Apa yang dibutuhkan:</p>
<ol>
<li>Raspberry pi 3</li>
<li>Microsd</li>
<li>Laptop/komputer</li>
<li>Card reader</li>
<li>Kabel LAN</li>
</ol>
<h2 id="here-what-i-did">Here, what i did</h2>
<ol>
<li>Download image raspbian <strong>lite</strong></li>
<li>Pasang microsd ke card reader.</li>
<li>Pasang card reader ke laptop.</li>
<li><code>dd</code> image raspbian lite ke microsd, kalau pakai ms windows gunakan aplikasi win32 disk imager.
Contohnya:
bash
sudo dd if=/lokasi/image/raspbian.img of=/lokasi/microsd/sdx bs=4MB && sync</li>
</ol>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>5. Tunggu proses dd sampai selesai
</span><span>6. Kalau sudah selesai _eject_ lalu pasang ke laptop lagi.
</span><span>7. Enable `ssh`, caranya:
</span><span>- masuk ke folder `boot`
</span><span>- buat file dengan nama `ssh` (tanpa ekstensi, tanpa isi)
</span><span>
</span><span>8. Kalau sudah selesai _eject_ lalu pasang ke raspberry pi 3 dan hidupkan raspi 3 nya.
</span><span>9. Sembari menunggu raspi3 untuk boot, siapkan beberapa hal berikut:
</span><span>- Aktifkan dhcp server untuk port lan di laptop, terserah mau pakai cara apa. misalnya pakai metode share koneksi wlan ke ethernet.
</span><span>- pasang kabel lan di raspi dan di laptop.
</span><span>
</span><span>10. Scan IP address milik raspberry pi 3, ini dilakukan karena IP address yg diperoleh raspi itu random dari dhcp. Di gnu/linux, saya pakai nmap. Kalau di ms windows pakai angry ip scanner. Contohnya:
</span><span>bash
</span><span>sudo nmap -sP 10.42.1.0/24
</span></code></pre>
<p><code>10.42.1.0/24</code> dapat darimana? dari <code>ifconfig</code> . Nah nanti muncul begini:
bash
Starting Nmap 7.40 ( https://nmap.org ) at 2017-04-16 11:51 WIB
Nmap scan report for 10.42.1.10
Host is up (0.00032s latency).
MAC Address: xx:xx:xx:xx:xx:xx (Raspberry Pi Foundation)
Nmap scan report for 10.42.1.53
Host is up (0.00022s latency).</p>
<pre style="background-color:#fcf0ca;color:#282828aa;"><code><span>
</span><span>11. Setelah diperoleh IP address milik raspi misalnya 10.42.1.53, lakukan ssh ke raspi 3, dengan `user: pi` dan `pass: raspberry` Kalau di windows bisa menggunakan putty atau bitvise ssh client.
</span><span>Contohnya:
</span><span>bash
</span><span>ssh pi@10.42.1.53
</span></code></pre>
<ol start="11">
<li>Selesai</li>
</ol>
<p>Nah itu tadi tentang apa yang saya lakukan untuk mengakses raspberry pi 3 dari laptop.</p>
Pertama kali memiliki raspberry pi 3
2017-04-14T19:02:00+07:00
2017-04-14T19:02:00+07:00
Unknown
https://www.sumarsono.com/meet-my-pi-3/
<p>Belum lama ini, keinginan saya untuk meminang raspberry pi 3 terkabul. Tulisan ini akan berisi apa saja yang saya lakukan pertama kali
bersama raspberry pi 3, semacam malam pertama.</p>
<h3 id="memberi-nafkah">Memberi Nafkah</h3>
<p>Yap, yang pertama adalah memberinya nafkah, berupa adaptor 5V 3A. Ini penting karena raspi 3 tidak bisa hidup tanpanya.</p>
<h3 id="memberinya-asupan-yang-baik">Memberinya asupan yang baik</h3>
<p>Selanjutnya saya memberinya asupan makanan berupa raspbian. Raspbian yang tersedia ada versi <strong>Pixel</strong> dan versi <strong>Lite</strong>.</p>
<h3 id="memberinya-pakaian">Memberinya pakaian</h3>
<p>Kasihan melihatnya telanjang, akhirnya saya belikan dia <strong>case</strong> dari bahan akrilik bening.</p>
<h3 id="membuatnya-nyaman">Membuatnya nyaman</h3>
<p>Setelah semua itu, saya harus membuatnya nyaman agar selalu awet. Yap, saya belikan dia pendingin agar tidak gerah. Sebuah kipas mini, <code>5V 0.20A</code>.</p>
<p>itulah tadi kisah kecil antara aku dan raspberry pi 3.</p>