Category: Uncategorized

  • WireGuard wg0 Not Starting After Reboot on Ubuntu



    If you’re using WireGuard on Ubuntu and notice that your wg0 interface
    does not start automatically after reboot, you’re not alone. This is a common issue—and fortunately, an easy one to fix.



    🚨 Problem



    After rebooting your Ubuntu system, the WireGuard interface wg0 is down,
    even though it worked perfectly before restarting.



    🤔 Why This Happens



    When you manually start WireGuard using:



    sudo wg-quick up wg0



    it only activates the VPN for the current session. It does not persist across reboots
    because the service has not been enabled in systemd.



    ✅ Solution: Enable WireGuard Auto-Start



    To ensure WireGuard starts automatically when your system boots, run:



    sudo systemctl enable wg-quick@wg0
    sudo systemctl start wg-quick@wg0



    This registers WireGuard as a system service and ensures wg0 starts at boot.



    🔍 Verify It’s Working


    sudo systemctl status wg-quick@wg0
    ip a show wg0



    If everything is configured correctly, you should see the interface active.



    ⚠️ Common Issues & Fixes



    1. Incorrect Config File Location



    Ensure your configuration file exists at:


    /etc/wireguard/wg0.conf


    2. File Permissions


    sudo chmod 600 /etc/wireguard/wg0.conf


    3. Network Not Ready at Boot



    Sometimes WireGuard starts before the network is fully initialized.
    Fix this by delaying startup:



    sudo systemctl edit wg-quick@wg0


    Add the following:



    [Unit]
    After=network-online.target
    Wants=network-online.target


    sudo systemctl daemon-reexec


    4. DNS Issues



    If you’re using the DNS= option in your config, ensure your system supports it
    (e.g., systemd-resolved or resolvconf).



    📊 Diagram: How WireGuard Startup Works




    ┌───────────────┐
    │ System Boot │
    └──────┬────────┘


    ┌──────────────────────┐
    │ systemd initializes │
    └──────┬───────────────┘


    ┌──────────────────────────────┐
    │ wg-quick@wg0.service enabled?│
    └──────┬───────────────┬───────┘
    │ YES │ NO
    ▼ ▼
    ┌───────────────┐ ┌──────────────┐
    │ Start wg0 VPN │ │ wg0 stays OFF│
    └───────────────┘ └──────────────┘


    📌 Summary



    • Problem: wg0 not starting after reboot

    • Cause: Service not enabled

    • Fix: systemctl enable wg-quick@wg0



    💡 Final Thoughts



    Enabling WireGuard at boot ensures your VPN connection is always active without manual intervention.
    This is especially important for servers, remote access setups, and privacy-focused configurations.



  • 如何避免ai GPT胡說八道

    告別「正確的廢話」:掌握 Gemini 3 的三大進階核心技巧

    許多人使用 Gemini 3 的方式仍停留在兩年前的搜尋框模式,僅輸入零散指令,導致 AI 只能回覆泛泛而談的內容。為了真正發揮這款最新一代推理模型的潛力,我們需要從系統指令、交互禁忌與幻覺規避三個維度進行深度優化。

    一、 編寫系統指令:打造「量身定制」的專屬 AI

    **系統指令(System Instruction)**或 Gemini 官網的 Gems 功能,能定義大模型的基礎行為準則,並在全局對話中生效。

    用戶畫像與偏好: 讓 AI 了解您的硬體環境(如 Windows 11 或特定顯卡)、身份背景(如無法註冊公司、所在地點)甚至是健康狀況。例如,若設定了高血脂背景,AI 在推薦美食時會自動避開不合適的選項。

    行為與人設: 您可以要求 AI 禁止諂媚,必須一針見血地指出錯誤,並在遇到不確定的資訊時直接承認「查不到」,而非胡編亂造。

    輸出規格: 指定特定的輸出格式(如 Markdown)或語言習慣(如術語需中英雙語並行),確保回覆內容能直接用於筆記軟體或商務文案。

    二、 交互禁忌:避免降低模型效率的錯誤行為

    根據 Google 官方文檔,Gemini 3 作為原生推理模型,有些傳統的提示詞技巧反而會適得其反:

    不要調整溫度(Temperature)與 Top P: Gemini 3 內建的思維鏈推理機制依賴高熵值進行路徑探索,調低溫度會破壞推理鏈

    不再需要「請一步步思考」: 這類指令會讓原生推理模型感到困惑,正確做法是給予具體的約束條件,引導其檢查特定邏輯。

    拒絕情緒勒索與贅字: 現代模型已能識別「越獄」技巧或低質量提示詞,過多廢話會稀釋關鍵詞權重。建議使用 XML 或 Markdown 格式的結構化指令,且不要混合使用不同格式以免解析混亂。

    三、 幻覺規避:確保答案的準確性

    AI 為了得分往往傾向於「猜測」而非承認無知,Gemini 3 Pro 的幻覺率甚至高於部分輕量模型,因為它更敢於推測複雜問題。

    引入 RAG(檢索增強生成): 利用最新更新的 NotebookLM 功能,將參考資料上傳,讓 AI 結合您提供的文檔與網絡搜尋來回答,能大幅降低幻覺。

    交叉驗證法: 讓一個 AI 生成內容後,交給另一個 AI 進行教驗。

    質疑前提: 在系統指令中要求 AI 優先審視用戶假設。若用戶給出的前提錯誤,AI 應主動反駁而非順著錯誤邏輯發展。

    Reference

  • 密碼產生器

    # pwgen

    pwgen -s 20

    產生20字符的密碼

  • Nextcloud + Onlyoffice deploy by using yml

    最近一段時間密集使用 Docker 佈署各種應用服務,一開始其實沒有特別留意系統資源的使用狀況。直到某一天,突然發現主機前方的系統運作指示燈幾乎沒有熄滅過,心裡只覺得怪怪的。打開系統監控工具一看,才發現事情大條了 —— RAM 幾乎被吃光。

    檢查後發現,原來「資源消耗怪獸」是:

    Nextcloud + OnlyOffice(Community Server + Document Server + Elasticsearch)+ MySQL

    光是完成佈署、系統閒置、甚至還沒做任何壓力測試,記憶體使用量就已經輕鬆突破 10GB

    「好吧,那就買 RAM 來改善把~~~」

    一查價格,我的老天鵝啊~~~~~ 今年 2 月才剛組了一台新電腦,同樣品牌、同樣型號。 32GB RAM,當時大約 NT$2,800。現在再查看一次價格 —— 接近3倍旳 NT$9,900。

    回想幾個星期前,曾在某個平台(一時想不起來是哪裡)聽到有人提到:

    由於 AI 需求動能強勁記憶體(RAM)價格正在快速上漲,且漲勢仍在持續。

    當時心裡還想:「能漲到什麼程度?」
    現在才發現自己真的是天真了。

    目前先將佈署流程與設定完整記錄下來,才不會以後忘記佈署的細節。接下來打算利用現有的 2 台電腦,練習如何將不同的 service 佈署在不同的 server 上協同運作,分散 RAM 與 I/O 的資源消耗。

    Bash Script × 2, dirCREATOR / initSQL
    Docker Compose(yml)× 1
    .env x1

    dirCREATOR
    負責根據 docker-compose.yml 中定義的 volume 結構,自動建立所有必要的資料夾與目錄階層。

    initSQL
    剛開始佈署,在這卡了很久。 Docker Compose 初始啟動時,SQL 初始化存在 bug,如果沒有先將SQL初始化搞定,會一直卡關。

    佈署流程

    dirCREATOR

    initSQL

    docker compose up -d


    dirCREATOR

    #!/usr/bin/env bash
    
    # Base data directory relative to the script location
    BASE_DIR="./data"
    
    echo "Creating directory structure for Nextcloud + OnlyOffice ( community + document + elacticsearch ) + MySQL"
    
    # Format: "path:owner_uid:group_gid:permissions"
    DIRS=(
        "$BASE_DIR/nextcloud_data:33:33:750"
        "$BASE_DIR/mysql/conf.d:0:0:755"
        "$BASE_DIR/mysql/docker-entrypoint-initdb.d:0:0:755"
        "$BASE_DIR/mysql_data:999:999:750"
        "$BASE_DIR/community_data:0:0:755"
        "$BASE_DIR/community_log:0:0:755"
        "$BASE_DIR/community_letsencrypt:0:0:755"
        "$BASE_DIR/document_data:0:0:755"
        "$BASE_DIR/document_log:0:0:755"
        "$BASE_DIR/document_forgotten:0:0:755"
        "$BASE_DIR/document_fonts:0:0:755"
        "$BASE_DIR/certs:0:0:755"
        "$BASE_DIR/es_data:1000:1000:775"
        "$BASE_DIR/mail_data:0:0:755"
        "$BASE_DIR/mail_certs:0:0:755"
        "$BASE_DIR/mail_log:0:0:755"
        "$BASE_DIR/controlpanel_data:0:0:755"
        "$BASE_DIR/controlpanel_log:0:0:755"
    )
    
    if [ "$EUID" -ne 0 ]; then
        echo "Please run as root (use sudo)"
        exit 1
    fi
    
    for entry in "${DIRS[@]}"; do
        IFS=':' read -r path uid gid perm <<< "$entry"
        echo "Processing: $path"
        mkdir -p "$path"
        chown "$uid:$gid" "$path"
        chmod "$perm" "$path"
    done
    
    echo "Directory setup complete."

    initSQL

    #!/usr/bin/env bash
    # --- ONLYOFFICE & NEXTCLOUD MySQL Configuration Creator ---
    set -e
    
    # --- 1. Define Paths and Credentials ---
    BASE_DIR="./data/mysql"
    CONF_DIR="${BASE_DIR}/conf.d"
    INIT_DB_DIR="${BASE_DIR}/docker-entrypoint-initdb.d"
    CONF_FILE="${CONF_DIR}/onlyoffice.cnf"
    INIT_SQL_FILE="${INIT_DB_DIR}/init.sql"
    
    # Credentials
    OO_USER="onlyoffice"
    OO_PASS="adjust to your pass"
    MAIL_USER="onlyoffice_mail"
    MAIL_PASS="adjust to your pass"
    
    # Nextcloud Credentials
    NC_DB="nextcloud"
    NC_USER="onlyoffice"
    NC_PASS="adjust to your pass"
    
    # --- 2. Ensure Directories Exist ---
    echo "Ensuring configuration directories exist..."
    mkdir -p "$CONF_DIR"
    mkdir -p "$INIT_DB_DIR"
    
    # --- 3. Write MySQL Configuration ---
    echo "Writing MySQL configuration to ${CONF_FILE}..."
    cat << 'EOF' > "$CONF_FILE"
    [mysqld]
    sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
    max_allowed_packet=256M
    innodb_buffer_pool_size=1G
    innodb_log_file_size=256M
    innodb_flush_log_at_trx_commit=2
    character-set-server=utf8mb4
    collation-server=utf8mb4_unicode_ci
    binlog_format=ROW
    EOF
    
    # --- 4. Write Database Initialization Script ---
    echo "Writing database user initialization script to ${INIT_SQL_FILE}..."
    cat << EOF > "$INIT_SQL_FILE"
    -- 1. Create Databases
    CREATE DATABASE IF NOT EXISTS onlyoffice CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
    CREATE DATABASE IF NOT EXISTS onlyoffice_mailserver CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
    CREATE DATABASE IF NOT EXISTS ${NC_DB} CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
    
    -- 2. Create Users
    CREATE USER IF NOT EXISTS '${OO_USER}'@'%' IDENTIFIED WITH mysql_native_password BY '${OO_PASS}';
    CREATE USER IF NOT EXISTS '${MAIL_USER}'@'%' IDENTIFIED WITH mysql_native_password BY '${MAIL_PASS}';
    
    -- 3. Grant Privileges
    GRANT ALL PRIVILEGES ON onlyoffice.* TO '${OO_USER}'@'%';
    GRANT ALL PRIVILEGES ON onlyoffice_mailserver.* TO '${MAIL_USER}'@'%';
    GRANT ALL PRIVILEGES ON ${NC_DB}.* TO '${OO_USER}'@'%';
    
    -- 4. Finalize
    FLUSH PRIVILEGES;
    -- Set to Taipei time (+08:00)
    SET GLOBAL time_zone = '+08:00';
    EOF
    
    echo "Initial scripts created successfully."

    .env

    # -----------------------------
    # SYSTEM
    # -----------------------------
    TZ=Asia/Taipei
    MYSQL_ROOT_PASSWORD="adjust to your pass"
    
    # -----------------------------
    # DATABASE
    # -----------------------------
    MYSQL_SERVER_HOST=onlyoffice-mysql-server
    MYSQL_SERVER_USER=onlyoffice
    MYSQL_SERVER_PASS="adjust to your pass"
    MYSQL_SERVER_DB_NAME=onlyoffice
    
    # -----------------------------
    # MAIL
    # -----------------------------
    MAIL_SERVER_HOSTNAME="adjust to your hostname"
    MAIL_DB_NAME=onlyoffice_mailserver
    MAIL_DB_USER=onlyoffice_mail
    MAIL_DB_PASS="adjust to your pass"
    
    # -----------------------------
    # SMTP RELAY
    # -----------------------------
    MAIL_RELAY_HOST="adjust to your hostname"
    MAIL_RELAY_PORT=587
    MAIL_RELAY_USER="adjust to your email"
    MAIL_RELAY_PASSWD="adjust to your pass"
    
    
    # -----------------------------
    # SECURITY (UNIQUE FOR GERARDCHEN INSTANCE)
    # -----------------------------
    JWT_SECRET="adjust to your secret"
    
    DOCUMENT_SERVER_JWT_HEADER=AuthorizationJwt
    ONLYOFFICE_CORE_MACHINEKEY="adjust to your key"
    
    # -----------------------------
    # NEXTCLOUD
    # -----------------------------
    NEXTCLOUD_DB_PASSWORD="adjust to your pass"
    
    # -----------------------------
    # DOMAINS
    # -----------------------------
    CLOUD_DOMAIN="adjust to your url"
    OFFICE_DOMAIN="adjust to your url"
    DOCUMENT_DOMAIN="adjust to your url"

    docker-compose.yml

    services:
    # --- REDIS ---
    redis:
    image: redis:alpine
    container_name: onlyoffice-redis
    restart: always
    networks:
    - onlyoffice

    # --- MYSQL SERVER ---
    mysql-server:
    container_name: onlyoffice-mysql-server
    image: mysql:8.0.29
    environment:
    - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
    - TZ=${TZ}
    networks:
    - onlyoffice
    restart: always
    volumes:
    - ./data/mysql/conf.d:/etc/mysql/conf.d
    - ./data/mysql/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
    - ./data/mysql_data:/var/lib/mysql
    healthcheck:
    test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD}"]
    interval: 10s
    timeout: 5s
    retries: 10
    start_period: 30s

    # --- NEXTCLOUD ---
    nextcloud:
    image: nextcloud:latest
    container_name: nextcloud
    restart: always
    depends_on:
    mysql-server:
    condition: service_healthy
    redis:
    condition: service_started
    ports:
    - "port:80"
    environment:
    - MYSQL_HOST=onlyoffice-mysql-server
    - MYSQL_DATABASE=nextcloud
    - MYSQL_USER=${MYSQL_SERVER_USER}
    - MYSQL_PASSWORD=${MYSQL_SERVER_PASS}
    - NEXTCLOUD_TRUSTED_DOMAINS=${CLOUD_DOMAIN} domain.local 127.0.0.1
    - REDIS_HOST=redis
    - OVERWRITEPROTOCOL=https
    - OVERWRITEHOST=${CLOUD_DOMAIN}
    - TZ=${TZ}
    volumes:
    - ./data/nextcloud_data:/var/www/html
    - /mnt/path to your physical harddisk:/path to your physical harddisk
    - /mnt/path to your physical harddisk:/mnt/path to your physical harddisk
    - /mnt/path to your physical harddisk:/mnt/path to your physical harddisk
    - /mnt/path to your physical harddisk:/mnt/path to your physical harddisk:
    - onlyoffice

    # --- DOCUMENT SERVER ---
    onlyoffice-document-server:
    container_name: onlyoffice-document-server
    image: onlyoffice/documentserver:8.1
    restart: always
    environment:
    - JWT_ENABLED=true
    - JWT_SECRET=${JWT_SECRET}
    - JWT_HEADER=${DOCUMENT_SERVER_JWT_HEADER}
    - TZ=${TZ}
    - REDIS_SERVER_HOST=redis
    networks:
    - onlyoffice
    ports:
    - 'port:80'
    volumes:
    - ./data/document_data:/var/www/onlyoffice/Data
    - ./data/document_log:/var/log/office
    - ./data/document_fonts:/usr/share/fonts/truetype/custom
    - ./data/document_forgotten:/var/lib/onlyoffice/documentserver/App_Data/cache/files/forgotten

    # --- ONLYOFFICE COMMUNITY SERVER ---
    onlyoffice-community-server:
    container_name: onlyoffice-community-server
    image: onlyoffice/communityserver:12.6.0.1900
    depends_on:
    mysql-server:
    condition: service_healthy
    onlyoffice-document-server:
    condition: service_started
    redis:
    condition: service_started
    environment:
    - ONLYOFFICE_CORE_MACHINEKEY=${ONLYOFFICE_CORE_MACHINEKEY}
    - TZ=${TZ}
    - REDIS_SERVER_HOST=redis
    - DOCUMENT_SERVER_PORT_80_TCP_ADDR=onlyoffice-document-server
    - DOCUMENT_SERVER_PORT_80_TCP_PROTO=http
    - DOCUMENT_SERVER_URL_PUBLIC=https://${DOCUMENT_DOMAIN}/
    - DOCUMENT_SERVER_URL_INTERNAL=http://onlyoffice-document-server/
    - DOCUMENT_SERVER_JWT_ENABLED=true
    - DOCUMENT_SERVER_JWT_SECRET=${JWT_SECRET}
    - DOCUMENT_SERVER_JWT_HEADER=${DOCUMENT_SERVER_JWT_HEADER}
    - MYSQL_SERVER_HOST=onlyoffice-mysql-server
    - MYSQL_SERVER_DB_NAME=${MYSQL_SERVER_DB_NAME}
    - MYSQL_SERVER_USER=${MYSQL_SERVER_USER}
    - MYSQL_SERVER_PASS=${MYSQL_SERVER_PASS}
    networks:
    - onlyoffice
    ports:
    - 'port:80'
    privileged: true
    cgroup: host
    restart: always
    volumes:
    - ./data/community_data:/var/www/onlyoffice/Data
    - ./data/community_log:/var/log/onlyoffice
    - ./data/community_ds_data:/var/www/onlyoffice/DocumentServerData
    - /sys/fs/cgroup:/sys/fs/cgroup:rw
    - ./data/certs:/var/www/onlyoffice/Data/certs

    # --- ELASTICSEARCH ---
    onlyoffice-elasticsearch:
    image: onlyoffice/elasticsearch:7.16.3
    container_name: onlyoffice-elasticsearch
    restart: always
    environment:
    - discovery.type=single-node
    - bootstrap.memory_lock=true
    - "ES_JAVA_OPTS=-Xms1g -Xmx1g"
    networks:
    - onlyoffice
    ulimits:
    memlock:
    soft: -1
    hard: -1
    volumes:
    - ./data/es_data:/usr/share/elasticsearch/data

    # --- MAIL SERVER ---
    onlyoffice-mail-server:
    container_name: onlyoffice-mail-server
    image: onlyoffice/mailserver:1.6.75
    depends_on:
    mysql-server:
    condition: service_healthy
    hostname: ${MAIL_SERVER_HOSTNAME}
    environment:
    - MYSQL_SERVER=onlyoffice-mysql-server
    - MYSQL_SERVER_PORT=3306
    - MYSQL_ROOT_USER=${MAIL_DB_USER}
    - MYSQL_ROOT_PASSWD=${MAIL_DB_PASS}
    - MYSQL_SERVER_DB_NAME=${MAIL_DB_NAME}
    - TZ=${TZ}
    - MAIL_RELAY_HOST=${MAIL_RELAY_HOST}
    - MAIL_RELAY_PORT=${MAIL_RELAY_PORT}
    - MAIL_RELAY_USER=${MAIL_RELAY_USER}
    - MAIL_RELAY_PASSWD=${MAIL_RELAY_PASSWD}
    networks:
    - onlyoffice
    restart: always
    privileged: true
    volumes:
    - ./data/mail_data:/var/vmail
    - ./data/mail_certs:/etc/pki/tls/mailserver
    - ./data/mail_log:/var/log

    # --- CONTROL PANEL ---
    onlyoffice-control-panel:
    container_name: onlyoffice-control-panel
    image: onlyoffice/controlpanel:3.5.2.530
    depends_on:
    - onlyoffice-document-server
    - onlyoffice-mail-server
    - onlyoffice-community-server
    environment:
    - ONLYOFFICE_CORE_MACHINEKEY=${ONLYOFFICE_CORE_MACHINEKEY}
    - TZ=${TZ}
    restart: always
    volumes:
    - /var/run/docker.sock:/var/run/docker.sock
    - ./data/controlpanel_data:/var/www/onlyoffice/Data
    - ./data/controlpanel_log:/var/log/onlyoffice
    networks:
    - onlyoffice

    networks:
    onlyoffice:
    driver: 'bridge'
  • ERPNEXT deployment, 25-003, multitenancy, DNS based

    # 啟動 DNS based multitenancy

    bench config dns_multitenant on

    # 建立新的ERPNEXT位置

    bench new-site siteNAME

    可以利用下列bash script建立新的ERPNEXT site

    #/usr/bin/env bash
    
    bench new-site siteNAME \
     --db-host 127.0.0.1 \
     --db-port 3306 \
     --mariadb-root-username mariadbROOT \
     --mariadb-root-password mariadbROOT-password \
     --admin-password adminPASSWORD \
     --mariadb-user-host-login-scope='%' \
     --verbose

    # 建立新的tenancy

    bench --site siteNAME add-to-hosts
  • ERPNEXT deployment, 25-001, basic system setup

    OS, UBUNTU 24.04
    ERPNEXT, version 15

    sudo apt update && sudo apt upgrade -y
    sudo apt install -y python3 python3-pip python3-venv python3-dev
    sudo apt install -y redis-server git
    sudo apt install -y supervisor

    # install Node.js, official NodeSource

    # Remove older versions first
    sudo apt remove nodejs npm -y
    
    # Add NodeSource for Node.js 18.x
    curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
    
    # Install Node.js and npm
    sudo apt install -y nodejs
    

    # versions check

    node -v
    npm -v
    yarn -v
    redis-server -v

    step 03, crete user

    # 設定frappe系統使用者
    sudo useradd -m -d /dir/for/frappe -s /bin/bash frappe
    
    # 設定frappe密碼
    sudo passwd frappe
    
    # 增加frappe群組
    sudo groupadd groupname
    
    # 將使用者frappe, 加入群組frappe
    sudo usermod -aG frappe frappe
    
    # 將使用者frappe, 加入群組frappe
    sudo usermod -aG sudo frappe

    step 04, virtual env setup, bench install & initiate

    # move to frappe dir
    cd /dir/to/frappe
    
    # Switch to user
    su frappe
    
    # deploy python virtualenv & activate
    python3 -m venv virtualENV
    source /path/to/virtualenv
    
    # Install bench & check bench version
    pip3 install frappe-bench
    bench --version
    bench init --frappe-branch version-15 frappeBENCH

    # setup bench Instance for

    # move to frappe bench directory
    mv frappeBENCH
    
    
    # setup supervisor
    確認在/etc/supervisor/conf.d內是否有supervisor.conf. 如果沒有, 執行下列指令. 
    bench setup supervisor
    
    ln -s /path/to/frappeBench/config/supervisor.conf /etc/supervisor/conf.d
    
    sudo supervisorctl reload
    
    
    # 下載app
    bench get-app --branch version-15 erpnext
    bench get-app --branch version-15 payments
    bench get-app --branch version-15 hrms
    
    
    # 利用下列bash script 建立個別erpnext個別網站
    
    #!/usr/bin/env bash
    
    siteNAME=erpnext.gerardchen.com
    
      bench new-site $siteNAME \
      --db-host 127.0.0.1 \
      --db-port 4306 \
      --mariadb-root-username root \
      --mariadb-root-password password.for.root \
      --admin-password password for admin \
      --mariadb-user-host-login-scope='%' \
      --verbose
    
    
    # 啟動bench
    bench start
    
    # Install ERPNext app
    bench --site siteNAME install-app erpnext
    bench --site siteNAME install-app hrms
    bench --site siteNAME install-app payments

    # setup production server

    # enable scheduler service
    bench --site siteNAME enable-scheduler
    
    # disable maintenance mode
    bench --site siteNAME set-maintenance-mode off
    
    # setup production config
    sudo bench setup production [frappe-user]
    因為以virtualenv建立python3環境, 且沒有設定PATH
    退出使用者frappe, 以superuser身分設定
    sudo /path/to/virtualENV/bin/bench setup production [frappe-user]
    
    bench setup socketio

    # setup port

    bench set-nginx-port siteName port
    

    bench init frappe --frappe-branch version-15
    bench init site01-bench --frappe-branch version-14

    Reference