Просмотр исходного кода

Merge remote-tracking branch 'upstream/agile' into agile

visuddhinanda 2 лет назад
Родитель
Сommit
0177ec5764
81 измененных файлов с 2084 добавлено и 308 удалено
  1. 1 0
      .vscode/extensions.json
  2. 3 1
      .vscode/settings.json
  3. 4 0
      deploy/.gitignore
  4. 88 0
      deploy/README.md
  5. 8 0
      deploy/group_vars/all.yml
  6. 9 0
      deploy/mint.yml
  7. 4 0
      deploy/ping.yml
  8. 98 0
      deploy/roles/mint/tasks/main.yml
  9. 31 0
      deploy/roles/os/tasks/main.yml
  10. 22 0
      deploy/roles/os/tasks/sshd.yml
  11. 80 0
      deploy/roles/os/tasks/ulimits.yml
  12. 52 0
      deploy/roles/php/tasks/main.yml
  13. 6 0
      deploy/roles/ping/tasks/main.yml
  14. 14 0
      deploy/roles/ubuntu/tasks/clean.yml
  15. 14 0
      deploy/roles/ubuntu/tasks/init.yml
  16. 38 0
      deploy/roles/ubuntu/tasks/locales.yml
  17. 157 0
      deploy/roles/ubuntu/tasks/main.yml
  18. 37 0
      deploy/roles/ubuntu/tasks/zsh.yml
  19. 44 0
      deploy/scripts/assets.sh
  20. 18 0
      deploy/scripts/dashboard.sh
  21. 48 0
      deploy/scripts/handbooks.sh
  22. 79 0
      deploy/scripts/laravel-react.sh
  23. 13 0
      deploy/scripts/sim_sent.sh
  24. 20 0
      deploy/scripts/sqlite_fix.sh
  25. 1 0
      deploy/staging/.gitignore
  26. 12 0
      deploy/staging/hosts
  27. 22 0
      docker/README.md
  28. 2 7
      docker/alpine/start.sh
  29. 110 0
      docker/focal/Dockerfile
  30. 16 0
      docker/focal/build.sh
  31. 11 0
      docker/focal/start.sh
  32. 21 248
      docker/jammy/Dockerfile
  33. 1 1
      docker/jammy/build.sh
  34. 2 7
      docker/jammy/start.sh
  35. 316 0
      docker/spring/Dockerfile
  36. 63 0
      docker/spring/README.md
  37. 16 0
      docker/spring/build.sh
  38. 0 0
      docker/spring/conan/conanfile.txt
  39. 0 0
      docker/spring/conan/install.sh
  40. 0 0
      docker/spring/conan/profiles/amd64
  41. 0 0
      docker/spring/conan/profiles/arm64
  42. 0 0
      docker/spring/conan/profiles/armhf
  43. 0 0
      docker/spring/conan/toolchains/amd64.cmake
  44. 0 0
      docker/spring/conan/toolchains/arm64.cmake
  45. 0 0
      docker/spring/conan/toolchains/armhf.cmake
  46. 0 0
      docker/spring/etc/envoy.yaml
  47. 1 0
      docker/spring/etc/nginx.conf
  48. 0 0
      docker/spring/etc/redis/clusters-init.sh
  49. 0 0
      docker/spring/etc/redis/node-1.conf
  50. 0 0
      docker/spring/etc/redis/node-2.conf
  51. 0 0
      docker/spring/etc/redis/node-3.conf
  52. 0 0
      docker/spring/etc/redis/node-4.conf
  53. 0 0
      docker/spring/etc/redis/node-5.conf
  54. 0 0
      docker/spring/etc/redis/node-6.conf
  55. 0 0
      docker/spring/etc/redis/node-s.conf
  56. 0 0
      docker/spring/etc/supervisor/conf.d/envoy.conf
  57. 0 0
      docker/spring/etc/supervisor/conf.d/minio.conf
  58. 0 0
      docker/spring/etc/supervisor/conf.d/mysql.conf
  59. 0 0
      docker/spring/etc/supervisor/conf.d/nginx.conf
  60. 0 0
      docker/spring/etc/supervisor/conf.d/opensearch.conf
  61. 0 0
      docker/spring/etc/supervisor/conf.d/php-fpm.conf
  62. 0 0
      docker/spring/etc/supervisor/conf.d/postgresql.conf
  63. 0 0
      docker/spring/etc/supervisor/conf.d/rabbitmq.conf
  64. 0 0
      docker/spring/etc/supervisor/conf.d/redis.conf
  65. 0 0
      docker/spring/etc/supervisor/supervisord.conf
  66. 11 0
      docker/spring/start.sh
  67. 28 0
      scripts/dashboard/deploy.sh
  68. 11 0
      scripts/dashboard/pack.sh
  69. 97 0
      scripts/dashboard/third.sh
  70. 25 0
      scripts/ops/hugo.sh
  71. 5 0
      scripts/ops/minio/README.md
  72. 98 0
      scripts/ops/minio/setup.sh
  73. 5 0
      scripts/ops/nginx/README.md
  74. 58 0
      scripts/ops/nginx/react.sh
  75. 16 0
      scripts/ops/redis/README.md
  76. 74 0
      scripts/ops/redis/setup.sh
  77. 18 0
      scripts/spring/README.md
  78. 74 0
      scripts/spring/Vagrantfile
  79. 7 0
      scripts/spring/user/README.md
  80. 34 17
      scripts/spring/user/create.sh
  81. 41 27
      scripts/spring/user/setup.sh

+ 1 - 0
.vscode/extensions.json

@@ -4,6 +4,7 @@
     "ms-python.python",
     "golang.go",
     "rust-lang.rust-analyzer",
+    "bmewburn.vscode-intelephense-client",
     "redhat.ansible",
     "redhat.vscode-xml",
     "redhat.vscode-yaml",

+ 3 - 1
.vscode/settings.json

@@ -9,7 +9,6 @@
     "source.fixAll.eslint": true
   },
   "editor.defaultFormatter": "esbenp.prettier-vscode",
-  "rust-analyzer.cargo.runBuildScripts": true,
   // https://code.visualstudio.com/docs/setup/linux#_visual-studio-code-is-unable-to-watch-for-file-changes-in-this-large-workspace-error-enospc
   "files.watcherExclude": {
     "**/.git/**": true,
@@ -29,5 +28,8 @@
   },
   "[python]": {
     "editor.defaultFormatter": "ms-python.python"
+  },
+  "[php]": {
+    "editor.defaultFormatter": "bmewburn.vscode-intelephense-client"
   }
 }

+ 4 - 0
deploy/.gitignore

@@ -0,0 +1,4 @@
+/clients/
+/tmp/
+/roles/mint/files/dashboard/
+*.log

+ 88 - 0
deploy/README.md

@@ -0,0 +1,88 @@
+# Deployment
+
+## Setup a cluster
+
+```bash
+# create cluster
+mkdir -p clients/CLUSTER/.ssh
+cd clients/CLUSTER
+# append your cluster hosts
+touch hosts
+# generate ssh key
+ssh-keygen -t ed25519 -f .ssh/id_ed25519
+# upload the ssh public key to target host
+ssh-copy-id -i .ssh/id_ed25519 USER@HOST
+```
+
+## Deploy
+
+```bash
+# test ssh connections
+peony -i clients/CLUSTER JOB.yml
+# run on all hosts
+peony -i clients/CLUSTER JOB.yml
+# run on only group
+peony -i clients/CLUSTER JOB.yml -l GROUP
+```
+
+## System image
+
+- [Raspberry Pi OS Lite](https://www.raspberrypi.com/software/operating-systems/)
+- [Armbian](https://www.armbian.com/download/)
+- [wiringPi for Orange Pi](https://github.com/orangepi-xunlong/WiringOP)
+
+## Import Database Data
+
+### on deploy a new server
+
+```bash
+php ../../public/app/install/db_insert_templet_cli.php 1 217
+php ../../public/app/install/db_update_toc_cli.php 1 217 pali
+php ../../public/app/install/db_update_toc_cli.php 1 217 zh-hans
+php ../../public/app/install/db_update_toc_cli.php 1 217 zh-hant
+php ../../public/app/install/db_insert_palitext_cli.php 1 217
+php ../../public/app/install/db_update_palitext_cli.php 1 217
+php ../../public/app/install/db_insert_bookword_from_csv_cli.php 1 217
+php ../../public/app/install/db_insert_word_from_csv_cli.php 1 217
+php ../../public/app/install/db_insert_wordindex_from_csv_cli.php
+
+php ./migrations/20211202084900_init_pali_serieses.php
+php ./migrations/20211125155600_word_statistics.php
+php ./migrations/20211125155700_pali_sent_org.php
+php ./migrations/20211125165700-pali_sent-upgrade.php
+php ./migrations/20211126220400-pali_sent_index-upgrade.php
+php ./migrations/20211127214800_sent_sim.php
+php ./migrations/20211127214900-sent_sim_index.php
+
+php ../../public/app/fts/sql.php
+
+php ../../public/app/admin/word_index_weight_refresh.php 1 217
+```
+
+### on update
+
+```bash
+# public/pali_title目录下文件*_pali.csv改变时触发
+php ../../public/app/install/db_update_palitext_cli.php 1 217
+
+# public/pali_title目录下文件其他改变时触发
+php ../../public/app/install/db_update_toc_cli.php 1 217 pali
+php ../../public/app/install/db_update_toc_cli.php 1 217 zh-hans
+php ../../public/app/install/db_update_toc_cli.php 1 217 zh-hant
+
+# public/dependence/pali_sentence/data 目录下文件其他改变时触发
+# TODO 导入pali_sent使用上述目录csv文件。目前用的是sqlite db文件
+php ./migrations/20211125165700-pali_sent-upgrade.php
+php ./migrations/20211126220400-pali_sent_index-upgrade.php
+
+```
+
+## Crontab
+
+### Daily
+
+1. upgrade_pali_toc.php
+
+```bash
+/public/app/upgrade/upgrade_pali_toc.php
+```

+ 8 - 0
deploy/group_vars/all.yml

@@ -0,0 +1,8 @@
+ansible_user: "deploy"
+ansible_python_interpreter: /usr/bin/python3
+ansible_ssh_private_key_file: "{{ inventory_dir }}/.ssh/id_ed25519"
+
+app_deploy_target: "/var/www/{{ inventory_hostname }}"
+app_php_version: "8.1"
+app_downloads: "{{ ansible_env.HOME }}/downloads"
+app_backup: "{{ ansible_env.HOME }}/backups"

+ 9 - 0
deploy/mint.yml

@@ -0,0 +1,9 @@
+- hosts: all
+  roles:
+    - ubuntu
+    - os
+
+- hosts: www
+  roles:
+    - php
+    - mint

+ 4 - 0
deploy/ping.yml

@@ -0,0 +1,4 @@
+- hosts: all
+  roles:
+    - ping
+

+ 98 - 0
deploy/roles/mint/tasks/main.yml

@@ -0,0 +1,98 @@
+- name: Git checkout source code(laravel)
+  ansible.builtin.git:
+    repo: "https://github.com/iapt-platform/mint.git"
+    dest: "{{ app_deploy_target }}/htdocs"
+    version: laravel
+    force: true
+
+- name: Install v2 nodejs dependencies(laravel)
+  ansible.builtin.shell: npm install
+  args:
+    chdir: "{{ app_deploy_target }}/htdocs"
+
+# TODO will remove in future
+- name: Install v1 php dependencies(laravel)
+  ansible.builtin.shell: "php{{ app_php_version }} {{ ansible_env.HOME }}/.local/bin/composer install"
+  args:
+    chdir: "{{ app_deploy_target }}/htdocs/public"
+
+# TODO will remove in future
+- name: Install v1 nodejs dependencies(laravel)
+  ansible.builtin.shell: npm install
+  args:
+    chdir: "{{ app_deploy_target }}/htdocs/public"
+
+# TODO will remove in future
+- name: Setup tmp folder(laravel)
+  become: true
+  ansible.builtin.file:
+    path: "{{ app_deploy_target }}/tmp"
+    state: directory
+    recurse: true
+    owner: www-data
+    group: www-data
+
+# TODO will remove in future
+- name: Install v1 tmp(laravel)
+  ansible.builtin.file:
+    src: "{{ app_deploy_target }}/tmp"
+    dest: "{{ app_deploy_target }}/htdocs/public/tmp"
+    state: link
+
+- name: Install v2 php dependencies
+  ansible.builtin.shell: "php{{ app_php_version }} {{ ansible_env.HOME }}/.local/bin/composer install"
+  args:
+    chdir: "{{ app_deploy_target }}/htdocs"
+
+- name: Setup storage folder(laravel)
+  become: true
+  ansible.builtin.file:
+    path: "{{ app_deploy_target }}/storage"
+    state: directory
+    recurse: true
+    owner: www-data
+    group: www-data
+
+- name: Delete repo's storage folder(laravel)
+  ansible.builtin.file:
+    path: "{{ app_deploy_target }}/htdocs/storage"
+    state: absent
+
+- name: create storage link(laravel)
+  ansible.builtin.file:
+    src: "{{ app_deploy_target }}/storage"
+    dest: "{{ app_deploy_target }}/htdocs/storage"
+    state: link
+
+- name: create v2 config file(laravel)
+  ansible.builtin.file:
+    src: "{{ app_deploy_target }}/etc/v2.env"
+    dest: "{{ app_deploy_target }}/htdocs/.env"
+    state: link
+
+# FIXME
+- name: create v1 config file(laravel)
+  ansible.builtin.file:
+    src: "{{ app_deploy_target }}/etc/v1.php"
+    dest: "{{ app_deploy_target }}/htdocs/public/app/config.php"
+    state: link
+
+- name: Git checkout source code(agile)
+  ansible.builtin.git:
+    repo: "https://github.com/iapt-platform/mint.git"
+    dest: "{{ app_deploy_target }}/agile"
+    version: agile
+
+- name: Install dashboard dependencies(agile)
+  ansible.builtin.shell: yarn install
+  args:
+    chdir: "{{ app_deploy_target }}/agile/dashboard"
+
+- name: Upload dashboard folder
+  ansible.builtin.copy:
+    src: dashboard
+    dest: "{{ app_deploy_target }}/"
+# - name: Build dashboard (agile)
+#   ansible.builtin.shell: NODE_OPTIONS=--max-old-space-size=1024 GENERATE_SOURCEMAP=false BUILD_PATH={{ app_deploy_target }}/dashboard PUBLIC_URL=/pcd yarn build
+#   args:
+#     chdir: "{{ app_deploy_target }}/agile/dashboard"

+ 31 - 0
deploy/roles/os/tasks/main.yml

@@ -0,0 +1,31 @@
+- import_tasks: sshd.yml
+- import_tasks: ulimits.yml
+
+- name: Reset root password
+  become: true
+  shell: echo "root:$(pwgen 32 1)" | chpasswd
+
+- name: Reset {{ ansible_user }} password
+  become: true
+  shell: echo "{{ ansible_user }}:$(pwgen 32 1)" | chpasswd
+  when: ansible_user != 'root'
+
+- name: Set timezone
+  become: true
+  shell: timedatectl set-timezone UTC
+
+- name: Setup journald storage
+  become: true
+  lineinfile:
+    path: /etc/systemd/journald.conf
+    regexp: "^#Storage="
+    line: Storage=persistent
+
+# https://www.linode.com/docs/quick-answers/linux/how-to-use-journalctl/
+- name: Setup journald storage keep-free
+  become: true
+  lineinfile:
+    path: /etc/systemd/journald.conf
+    state: present
+    regexp: "^#SystemKeepFree="
+    line: SystemKeepFree=6%

+ 22 - 0
deploy/roles/os/tasks/sshd.yml

@@ -0,0 +1,22 @@
+- name: Backup sshd_config
+  become: true
+  copy:
+    src: /etc/ssh/sshd_config
+    dest: "{{ app_backup }}/etc_sshd_config"
+    remote_src: yes
+    backup: yes
+
+- name: Disable dns for sshd
+  become: true
+  lineinfile:
+    path: /etc/ssh/sshd_config
+    regexp: '^UseDNS '
+    line: UseDNS no
+
+- name: Disable GSS api auth for sshd
+  become: true
+  lineinfile:
+    path: /etc/ssh/sshd_config
+    regexp: '^GSSAPIAuthentication '
+    line: GSSAPIAuthentication no
+

+ 80 - 0
deploy/roles/os/tasks/ulimits.yml

@@ -0,0 +1,80 @@
+- name: Backup system.conf
+  become: true
+  copy:
+    src: /etc/systemd/system.conf
+    dest: "{{ app_backup }}/etc_systemd_system"
+    remote_src: yes
+    backup: yes
+
+- name: Setup nofile for system
+  become: true
+  lineinfile:
+    path: /etc/systemd/system.conf
+    regexp: "^DefaultLimitNOFILE="
+    line: DefaultLimitNOFILE=2097152
+
+- name: Setup nproc for system
+  become: true
+  lineinfile:
+    path: /etc/systemd/system.conf
+    regexp: "^DefaultLimitNPROC"
+    line: DefaultLimitNPROC=524288
+
+- name: Backup user.conf
+  become: true
+  copy:
+    src: /etc/systemd/user.conf
+    dest: "{{ app_backup }}/etc_systemd_user.conf"
+    remote_src: yes
+    backup: yes
+
+- name: Setup nofile for user
+  become: true
+  lineinfile:
+    path: /etc/systemd/user.conf
+    regexp: "^DefaultLimitNOFILE="
+    line: DefaultLimitNOFILE=1048576
+
+- name: Setup nproc for user
+  become: true
+  lineinfile:
+    path: /etc/systemd/user.conf
+    regexp: "^DefaultLimitNPROC"
+    line: DefaultLimitNPROC=262144
+
+- name: Backup limits.conf
+  become: true
+  copy:
+    src: /etc/security/limits.conf
+    dest: "{{ app_backup }}/etc_security_limits.conf"
+    remote_src: yes
+    backup: yes
+
+- name: Set user level ppen file limits for root
+  become: true
+  lineinfile:
+    path: /etc/security/limits.conf
+    line: root        soft nofile 10240
+
+- name: Set user level open file limits for {{ ansible_user }}
+  become: true
+  lineinfile:
+    path: /etc/security/limits.conf
+    line: "{{ ansible_user }}        soft nofile 10240"
+
+# https://docs.oracle.com/en/database/oracle/oracle-database/12.2/ladbi/changing-kernel-parameter-values.html#GUID-FB0CC366-61C9-4AA2-9BE7-233EB6810A31
+- name: Setup file max
+  become: true
+  lineinfile:
+    path: "/etc/sysctl.d/100-fs.conf"
+    state: present
+    line: fs.file-max = 6815744
+    create: true
+
+- name: Setup file max
+  become: true
+  lineinfile:
+    path: "/etc/sysctl.d/100-fs.conf"
+    state: present
+    line: fs.inotify.max_user_watches = 512000
+    create: true

+ 52 - 0
deploy/roles/php/tasks/main.yml

@@ -0,0 +1,52 @@
+- name: Add php repository
+  become: true
+  ansible.builtin.apt_repository:
+    repo: ppa:ondrej/php
+
+- name: Install php packages
+  become: true
+  apt:
+    pkg:
+      - php{{ app_php_version }}-cli
+      - php{{ app_php_version }}-fpm
+      - php{{ app_php_version }}-xml
+      - php{{ app_php_version }}-imap
+      - php{{ app_php_version }}-intl
+      - php{{ app_php_version }}-mbstring
+      - php{{ app_php_version }}-bcmath
+      - php{{ app_php_version }}-bz2
+      - php{{ app_php_version }}-zip
+      - php{{ app_php_version }}-curl
+      - php{{ app_php_version }}-gd
+      - php{{ app_php_version }}-imagick
+      - php{{ app_php_version }}-pgsql
+      - php{{ app_php_version }}-mysql
+      - php{{ app_php_version }}-sqlite3
+      - php{{ app_php_version }}-redis
+      - php{{ app_php_version }}-amqp
+
+- name: Creates composer install directory
+  file:
+    path: "{{ ansible_env.HOME }}/.local/bin"
+    state: directory
+
+# https://getcomposer.org/doc/00-intro.md#installation-linux-unix-macos
+- name: Download composer
+  get_url:
+    url: https://getcomposer.org/download/latest-stable/composer.phar
+    dest: "{{ ansible_env.HOME }}/.local/bin/composer"
+    mode: 0755
+
+- name: Restart php-fpm
+  become: true
+  ansible.builtin.systemd:
+    state: restarted
+    daemon_reload: yes
+    name: "php{{ app_php_version }}-fpm"
+
+- name: Restart nginx
+  become: true
+  ansible.builtin.systemd:
+    state: restarted
+    daemon_reload: yes
+    name: nginx

+ 6 - 0
deploy/roles/ping/tasks/main.yml

@@ -0,0 +1,6 @@
+- name: Test ssh connection
+  ping:
+
+- name: Show facts available on the system
+  ansible.builtin.debug:
+    var: ansible_facts

+ 14 - 0
deploy/roles/ubuntu/tasks/clean.yml

@@ -0,0 +1,14 @@
+- name: Remove useless packages from the cache
+  become: true
+  apt:
+    autoclean: yes
+
+- name: Remove dependencies that are no longer required
+  become: true
+  apt:
+    autoremove: yes
+
+- name: Force systemd to reread configs
+  become: true
+  systemd:
+    daemon_reload: yes

+ 14 - 0
deploy/roles/ubuntu/tasks/init.yml

@@ -0,0 +1,14 @@
+- name: create downloads folder
+  become: true
+  ansible.builtin.file:
+    path: "{{ app_downloads }}"
+    state: directory
+    owner: "{{ ansible_user }}"
+
+- name: create backup folder
+  become: true
+  ansible.builtin.file:
+    path: "{{ app_backup }}"
+    state: directory
+    owner: "{{ ansible_user }}"
+

+ 38 - 0
deploy/roles/ubuntu/tasks/locales.yml

@@ -0,0 +1,38 @@
+- name: Backup locale.gen
+  become: true
+  copy:
+    src: /etc/locale.gen
+    dest: "{{ app_backup }}/etc_locale.gen"
+    remote_src: yes
+    backup: yes
+
+- name: Enable en-US locale
+  become: true
+  lineinfile:
+    path: /etc/locale.gen
+    state: present
+    line: en_US.UTF-8 UTF-8
+
+
+- name: Enable zh-CN locale
+  become: true
+  lineinfile:
+    path: /etc/locale.gen
+    state: present
+    line: zh_CN.UTF-8 UTF-8
+
+- name: Enable zh-TW locale
+  become: true
+  lineinfile:
+    path: /etc/locale.gen
+    state: present
+    line: zh_TW.UTF-8 UTF-8
+
+
+- name: Generate locales
+  become: true
+  shell: locale-gen
+
+- name: Use en_US as default locale
+  become: true
+  shell: update-locale LANG=en_US.UTF-8

+ 157 - 0
deploy/roles/ubuntu/tasks/main.yml

@@ -0,0 +1,157 @@
+- import_tasks: init.yml
+
+- name: add PPA for Ubuntu Toolchain
+  become: true
+  ansible.builtin.apt_repository:
+    repo: ppa:ubuntu-toolchain-r/test
+  when: ansible_distribution == 'Ubuntu'
+
+# https://classic.yarnpkg.com/lang/en/docs/install/#debian-stable
+- name: Add an yarn signing key
+  become: true
+  ansible.builtin.apt_key:
+    url: https://dl.yarnpkg.com/debian/pubkey.gpg
+    state: present
+  when: ansible_distribution == 'Ubuntu'
+
+- name: Add an yarn package repository
+  become: true
+  ansible.builtin.lineinfile:
+    path: /etc/apt/sources.list.d/yarn.list
+    line: "deb https://dl.yarnpkg.com/debian/ stable main"
+    create: true
+  when: ansible_distribution == 'Ubuntu'
+
+- name: Install nodejs
+  become: true
+  community.general.snap:
+    name: node
+    classic: true
+
+- name: Update system
+  become: true
+  apt:
+    upgrade: yes
+    update_cache: yes
+    cache_valid_time: 3600
+
+- name: Install dependicy packages
+  become: true
+  apt:
+    pkg:
+      - apt-transport-https
+      - software-properties-common
+      - gnupg
+      - openssh-server
+      - openssh-client
+      - sshpass
+      - wpasupplicant
+      - rsync
+      - at
+      - sysstat
+      - libtool
+      - ethtool
+      - dnsutils
+      - dnsmasq
+      - uuid-runtime
+      - lshw
+      - tcpdump
+      - lm-sensors
+      - dmidecode
+      - net-tools
+      - iputils-arping
+      - iputils-ping
+      - telnet
+      - vim
+      - git
+      - pwgen
+      - locales
+      - ntpdate
+      - imagemagick
+      - mpg123
+      - ffmpeg
+      - sqlite3
+      - tree
+      - alsa-utils
+      - pulseaudio
+      - zsh
+      - wget
+      - curl
+      - zip
+      - unzip
+      - nginx
+      - libnginx-mod-http-upstream-fair
+      - certbot
+      - python3-certbot-nginx
+      - openvpn
+      - snmpd
+      - mutt
+      - systemd-cron
+      - screen
+      - tmux
+      - hugo
+      - yarn
+      - python3
+      - python3-pip
+      - python3-distutils
+      - python3-dev
+      - libssl-dev
+      - libpq-dev
+      - libmysqlclient-dev
+      - libevent-dev
+
+- name: Install dependicy packages(>bionic)
+  become: true
+  apt:
+    pkg:
+      - systemd-timesyncd
+  # ansible_facts['distribution'] == "Ubuntu"
+  when: ansible_facts['distribution_major_version'] | int >= 20
+
+- import_tasks: locales.yml
+
+- name: Set default editor to vim
+  become: true
+  shell: update-alternatives --set editor /usr/bin/vim.basic
+
+- name: Set timezone
+  become: true
+  shell: timedatectl set-timezone UTC
+
+- name: Set git rebase mode
+  become: true
+  shell: git config --global pull.rebase false
+
+- import_tasks: zsh.yml
+
+# ---------------------------------------------------
+
+- name: enable nginx service
+  become: true
+  ansible.builtin.systemd:
+    name: nginx
+    enabled: yes
+    masked: no
+
+- name: enable cron service
+  become: true
+  ansible.builtin.systemd:
+    name: cron
+    enabled: yes
+    masked: no
+
+- name: enable ssh service
+  become: true
+  ansible.builtin.systemd:
+    name: ssh
+    enabled: yes
+    masked: no
+
+- name: enable systemd-timesyncd service
+  become: true
+  ansible.builtin.systemd:
+    name: systemd-timesyncd
+    enabled: yes
+    masked: no
+
+- import_tasks: clean.yml

+ 37 - 0
deploy/roles/ubuntu/tasks/zsh.yml

@@ -0,0 +1,37 @@
+- name: Clone oh-my-zsh
+  git:
+    repo: https://github.com/robbyrussell/oh-my-zsh.git
+    dest: "{{ansible_env.HOME}}/.oh-my-zsh"
+
+# - name: Extract ohmyzsh
+#   unarchive:
+#     src: ohmyzsh-master.zip
+#     dest: "{{ansible_env.HOME}}/"
+
+# - name: Rename ohmyzsh
+#   command: mv ohmyzsh-master .oh-my-zsh
+#   args:
+#     chdir: "{{ansible_env.HOME}}"
+#     creates: .oh-my-zsh
+
+- name: Setup .zshrc
+  copy:
+    src: "{{ansible_env.HOME}}/.oh-my-zsh/templates/zshrc.zsh-template"
+    dest: "{{ansible_env.HOME}}/.zshrc"
+    remote_src: true
+    mode: 0600
+
+- name: Enable $HOME/.local
+  ansible.builtin.lineinfile:
+    path: "{{ansible_env.HOME}}/.zshrc"
+    line: 'export PATH=$HOME/.local/bin:$PATH'
+
+
+- name: Setup EDITOR
+  ansible.builtin.lineinfile:
+    path: "{{ansible_env.HOME}}/.zshrc"
+    line: 'export EDITOR=vim'
+
+- name: Use zsh
+  become: true
+  shell: chsh -s /bin/zsh {{ansible_user}}

+ 44 - 0
deploy/scripts/assets.sh

@@ -0,0 +1,44 @@
+#!/bin/bash
+
+set -e
+
+# rclone copy --drive-shared-with-me $1:assets assets
+
+export WORKSPACE=$PWD
+
+function build_book(){
+    local target=$WORKSPACE/tmp/$1/$2
+    local dist=$WORKSPACE/roles/mint-assets/files/public/$1/$2
+    if [ ! -d $target ]
+    then
+        git clone -b $2 "https://github.com/iapt-platform/$1.git" $target
+    fi
+    cd $target
+    git pull
+    if [ -d $dist ]
+    then
+        rm -r $dist
+    fi
+    mkdir -p $dist
+    $HOME/.local/bin/mdbook build --dest-dir $dist
+}
+
+declare -a languages=(
+    "zh-Hans"
+)
+
+declare -a books=(
+    "pali-handbook"
+    "help"
+)
+
+for b in "${books[@]}"
+do
+    for l in "${languages[@]}"
+    do
+        build_book $b $l
+    done
+done
+
+echo 'done.'
+exit 0

+ 18 - 0
deploy/scripts/dashboard.sh

@@ -0,0 +1,18 @@
+#!/bin/bash
+
+set -e
+
+export WORKSPACE=$PWD
+
+cd $WORKSPACE/dashboard
+if [ ! -d node_modules ]
+then
+    yarn install
+fi
+
+# GENERATE_SOURCEMAP=false 
+BUILD_PATH=$WORKSPACE/deploy/roles/mint/files/dashboard PUBLIC_URL=/pcd yarn build
+
+echo 'done.'
+
+exit 0

+ 48 - 0
deploy/scripts/handbooks.sh

@@ -0,0 +1,48 @@
+#!/bin/bash
+
+set -e
+
+
+if [ $# -ne 1 ]
+then
+	echo "Usage: $0 FOLDER"
+	exit 1
+fi
+
+
+function build_book(){
+    local target=$HOME/tmp/$2/$3
+    local dist=$1/public/$2/$3
+    if [ ! -d $target ]
+    then
+        git clone -b $3 "https://github.com/iapt-platform/$2.git" $target
+    fi
+    cd $target
+    git pull
+    if [ -d $dist ]
+    then
+        rm -r $dist
+    fi
+    mkdir -p $dist
+    $HOME/.local/bin/mdbook build --dest-dir $dist
+    echo "done($dist)."
+}
+
+declare -a languages=(
+    "zh-Hans"
+)
+
+declare -a books=(
+    "pali-handbook"
+    "help"
+)
+
+for b in "${books[@]}"
+do
+    for l in "${languages[@]}"
+    do
+        build_book $1 $b $l
+    done
+done
+
+exit 0

+ 79 - 0
deploy/scripts/laravel-react.sh

@@ -0,0 +1,79 @@
+#!/bin/bash
+
+set -e
+
+
+if [ "$#" -ne 1 ]
+then
+    echo "USAGE: $0 DOMAIN"
+    exit 1
+fi
+
+echo "check $1.conf"
+if [ ! -d /var/www/$1/logs ]
+then
+  mkdir -p /var/www/$1/logs
+  chown -R www-data:www-data /var/www/$1/logs
+fi
+
+if [ ! -f /etc/nginx/sites-enabled/$1.conf ]
+then
+    # https://laravel.com/docs/10.x/deployment
+    cat > /etc/nginx/sites-enabled/$1.conf <<EOF
+server {
+
+  server_name $1;
+  root /var/www/$1/htdocs/public;
+  access_log /var/www/$1/logs/access.log;
+  error_log  /var/www/$1/logs/error.log;
+  
+  add_header X-Frame-Options "SAMEORIGIN";
+  add_header X-Content-Type-Options "nosniff";
+
+  index index.php;
+  charset utf-8;
+
+  gzip on;
+  gzip_comp_level 9;
+  gzip_min_length 1k;
+  gzip_types text/plain text/css application/xml application/javascript;
+  gzip_vary on;
+  client_max_body_size 128M;
+  
+
+  location /pcd/ {
+    alias /var/www/$1/dashboard/;
+    try_files \$uri \$uri/ /pcd/index.html;
+    
+    location ~* \\.(css|js|png|jpg|jpeg|gif|gz|svg|mp4|ogg|ogv|webm|htc|xml|woff)\$ {
+      access_log off;
+      expires max;
+    }
+  }
+  
+  location / {
+    try_files \$uri \$uri/ /index.php?\$query_string;
+  }
+
+  location = /favicon.ico { access_log off; log_not_found off; }
+  location = /robots.txt  { access_log off; log_not_found off; }
+  error_page 404 /index.php;
+
+  location ~ \.php\$ {
+    fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
+    fastcgi_param SCRIPT_FILENAME \$realpath_root\$fastcgi_script_name;
+    include fastcgi_params;
+  }
+ 
+  location ~ /\.(?!well-known).* {
+      deny all;
+  }
+
+}
+EOF
+
+    chmod 644 /etc/nginx/sites-enabled/$1.conf
+fi
+
+echo "done($1)."
+exit 0

+ 13 - 0
deploy/scripts/sim_sent.sh

@@ -0,0 +1,13 @@
+#!/bin/sh
+
+set -e
+
+export SIM=$(pgrep -f "php sim_sent")
+
+echo "find pid $SIM"
+renice +19 $SIM
+ionice -c 2 -n 7 -p $SIM
+
+echo "done."
+
+exit 0

+ 20 - 0
deploy/scripts/sqlite_fix.sh

@@ -0,0 +1,20 @@
+#!/bin/sh
+
+set -e
+if [ $# -ne 1 ]
+then
+	echo "Usage: $0 DB"
+	exit 1
+fi
+
+if [ ! -f $1 ]
+then
+	echo "$1 not exists"
+	exit 1
+fi
+
+echo '.dump'|sqlite3 $1|sqlite3 $1_repaired
+mv -v $1 $1_corrupt
+mv -v $1_repaired $1
+
+exit 0

+ 1 - 0
deploy/staging/.gitignore

@@ -0,0 +1 @@
+/.ssh/

+ 12 - 0
deploy/staging/hosts

@@ -0,0 +1,12 @@
+[www]
+
+
+[all:vars]
+; openssl rand -base64 32
+app_secret_key="4i3WKUvKtSGl59htK7XjUNsjalhkG5s7RJCmZruT2m4="
+; php artisan key:generate --show
+app_laravel_key="base64:IQD4vkmAN1oEsc8rVu1nRadQWPUX/LH/jaSbyFbmf/w="
+app_postgresql_host="db-hk-1.wikipali.org"
+app_postgresql_port=5433
+app_postgresql_password=change-me
+app_redis_host="ch-hk-1.wikipali.org"

+ 22 - 0
docker/README.md

@@ -0,0 +1,22 @@
+# Usage
+
+```bash
+sudo apt install crun podman buildah
+```
+
+- commands
+
+  ```bash
+  podman image prune # removes all dangling images
+  podman system reset # clean
+  podman images # show images
+  podman ps -a # show containers
+  podman load -i tmp/palm-CODE-TIMESTAMP.tar # import image
+  ```
+
+- Envoy build
+
+  ```bash
+  podman pull docker.io/envoyproxy/envoy-dev:latest
+  podman run --rm -it docker.io/envoyproxy/envoy-dev:latest
+  ```

+ 2 - 7
docker/alpine/start.sh

@@ -6,11 +6,6 @@ export NAME="$CODE-$USER"
 if podman container exists $NAME
 then
     podman start -i -a $NAME
-else
-    if [ "$(uname)" == "Darwin" ]
-    then
-        podman run --name $NAME -it --hostname=palm --network host -v $PWD:/workspace:z $CODE
-    else
-        podman run --name $NAME -it --events-backend=file --hostname=palm --network host -v $PWD:/workspace:z $CODE
-    fi
+else    
+    podman run --name $NAME -it --events-backend=file --hostname=palm --network host -v $PWD:/workspace:z $CODE
 fi

+ 110 - 0
docker/focal/Dockerfile

@@ -0,0 +1,110 @@
+FROM ubuntu:focal
+LABEL maintainer="Jeremy Zheng"
+
+ENV DEBIAN_FRONTEND noninteractive
+
+RUN apt update
+RUN apt install -y lsb-release
+RUN echo "deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ $(lsb_release -cs) main restricted universe multiverse" > /etc/apt/sources.list
+RUN echo "deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ $(lsb_release -cs)-updates main restricted universe multiverse" >> /etc/apt/sources.list
+RUN echo "deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ $(lsb_release -cs)-security main restricted universe multiverse" >> /etc/apt/sources.list
+RUN dpkg --add-architecture arm64
+RUN echo "deb [arch=arm64] http://ports.ubuntu.com/ $(lsb_release -cs) main restricted universe multiverse" >> /etc/apt/sources.list
+RUN echo "deb [arch=arm64] http://ports.ubuntu.com/ $(lsb_release -cs)-security main restricted universe multiverse" >> /etc/apt/sources.list
+RUN echo "deb [arch=arm64] http://ports.ubuntu.com/ $(lsb_release -cs)-updates main restricted universe multiverse" >> /etc/apt/sources.list
+RUN apt update && apt -y upgrade
+
+ENV GCC_VERSION 10
+ENV CLANG_VERSION 12
+RUN apt -y install zsh git locales locales-all \
+    vim tzdata zip unzip tree tmux \
+    build-essential crossbuild-essential-arm64 \
+    g++-${GCC_VERSION} g++-${GCC_VERSION}-aarch64-linux-gnu \
+    libstdc++-${GCC_VERSION}-dev:amd64 libstdc++-${GCC_VERSION}-dev:arm64 \
+    clang-${CLANG_VERSION} lldb-${CLANG_VERSION} lld-${CLANG_VERSION} \
+    cmake pkg-config libtool automake autoconf autoconf-archive binutils cpio \
+    debhelper bison flex ninja-build \
+    python3 python3-distutils python3-dev python3-pip virtualenv
+RUN update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-${CLANG_VERSION} 100 \
+    && update-alternatives --install /usr/bin/clang clang /usr/bin/clang-${CLANG_VERSION} 100 \
+    && update-alternatives --install /usr/bin/lldb lldb /usr/bin/lldb-${CLANG_VERSION} 100 \
+    && update-alternatives --install /usr/bin/lld lld /usr/bin/lld-${CLANG_VERSION} 100 \
+    && update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-${GCC_VERSION} 100 \
+    && update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-${GCC_VERSION} 100 \
+    && update-alternatives --install /usr/bin/aarch64-linux-gnu-gcc aarch64-linux-gnu-gcc /usr/bin/aarch64-linux-gnu-gcc-${GCC_VERSION} 100 \
+    && update-alternatives --install /usr/bin/aarch64-linux-gnu-g++ aarch64-linux-gnu-g++ /usr/bin/aarch64-linux-gnu-g++-${GCC_VERSION} 100
+
+RUN apt -y autoremove && apt -y clean
+
+RUN cd /usr/bin && ln -s make gmake
+RUN echo "en_US.UTF-8 UTF-8" > /etc/locale.gen
+RUN locale-gen
+RUN update-locale LANG=en_US.UTF-8
+RUN update-alternatives --set editor /usr/bin/vim.basic
+
+RUN mkdir -p $HOME/downloads $HOME/build $HOME/local $HOME/tmp
+
+# https://github.com/ohmyzsh/ohmyzsh
+RUN git clone https://github.com/ohmyzsh/ohmyzsh.git $HOME/.oh-my-zsh
+RUN cp $HOME/.oh-my-zsh/templates/zshrc.zsh-template $HOME/.zshrc
+RUN echo 'export LANG=en_US.UTF-8' >> $HOME/.zshrc
+RUN echo 'export LC_ALL=en_US.UTF-8' >> $HOME/.zshrc
+RUN echo 'export PATH=$HOME/.local/bin:$PATH' >> $HOME/.zshrc
+
+RUN git config --global core.quotepath false \
+    && git config --global http.version HTTP/1.1 \
+    && git config --global pull.rebase false \
+    && git config --global url."https://".insteadOf git://
+RUN echo 'set-option -g history-limit 102400' > $HOME/.tmux.conf \
+    && echo 'set-option -g default-shell "/bin/zsh"' >> $HOME/.tmux.conf
+
+# https://github.com/nvm-sh/nvm
+ENV NVM_VERSION "v0.39.3"
+RUN git clone -b ${NVM_VERSION} https://github.com/nvm-sh/nvm.git $HOME/.nvm
+RUN echo 'export NVM_DIR="$HOME/.nvm"' >> $HOME/.zshrc
+RUN echo '[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"' >> $HOME/.zshrc
+RUN echo '[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"' >> $HOME/.zshrc
+RUN zsh -c "source $HOME/.zshrc \
+    && nvm install node \
+    && nvm use node \
+    && npm i yarn -g"
+RUN echo 'export PATH=$HOME/.yarn/bin:$PATH' >> $HOME/.zshrc
+
+# https://www.rust-lang.org/tools/install
+RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
+RUN zsh -c "source $HOME/.cargo/env && rustup target add aarch64-unknown-linux-gnu"
+
+# https://github.com/rui314/mold
+RUN git clone -b v1.9.0 https://github.com/rui314/mold.git $HOME/downloads/mold
+RUN apt install -y g++-10 \
+    libssl-dev libxxhash-dev zlib1g-dev \
+    file bsdmainutils
+RUN zsh -c "source $HOME/.zshrc \
+    && mkdir $HOME/build/mold \
+    && cd $HOME/build/mold \
+    && cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=g++-10 \
+        -DCMAKE_INSTALL_PREFIX=$HOME/.local $HOME/downloads/mold \
+    && make -j \
+    && make install"
+RUN cp $HOME/.local/bin/mold /usr/bin/
+
+# https://github.com/grpc/grpc
+ENV GRPC_VERSION "v1.51.1"
+RUN git clone --recurse-submodules -b $GRPC_VERSION https://github.com/grpc/grpc.git $HOME/downloads/grpc
+RUN zsh -c "source $HOME/.zshrc \
+    && mkdir -pv $HOME/build/grpc \
+    && cd $HOME/build/grpc \
+    && cmake -DCMAKE_BUILD_TYPE=Release \
+        -DgRPC_INSTALL=ON \
+        -DgRPC_SSL_PROVIDER=package \
+        -DgRPC_BUILD_TESTS=OFF \
+        -DCMAKE_INSTALL_PREFIX=$HOME/.local $HOME/downloads/grpc \
+    && make -j \
+    && make install"
+
+RUN echo "$(date -u +%4Y%m%d%H%M%S)" | tee /VERSION
+
+VOLUME /workspace
+WORKDIR /workspace
+
+CMD ["/bin/zsh", "-l"]

+ 16 - 0
docker/focal/build.sh

@@ -0,0 +1,16 @@
+#!/bin/bash
+
+set -e
+
+export VERSION=$(date "+%4Y%m%d%H%M%S")
+export CODE="palm-focal"
+
+buildah pull ubuntu:focal
+buildah bud --layers -t $CODE .
+podman save -o $CODE-$VERSION.tar $CODE
+XZ_OPT=-9 tar -cJf $CODE-$VERSION.tar.xz $CODE-$VERSION.tar
+md5sum $CODE-$VERSION.tar* > md5.txt
+
+echo "done($CODE-$VERSION.tar.xz)."
+
+exit 0

+ 11 - 0
docker/focal/start.sh

@@ -0,0 +1,11 @@
+#!/bin/bash
+
+export CODE="palm-focal"
+export NAME="$CODE-$USER"
+
+if podman container exists $NAME
+then
+    podman start -i -a $NAME
+else    
+    podman run --name $NAME -it --events-backend=file --hostname=palm --network host -v $PWD:/workspace:z $CODE
+fi

+ 21 - 248
docker/jammy/Dockerfile

@@ -4,68 +4,23 @@ LABEL maintainer="Jeremy Zheng"
 ENV DEBIAN_FRONTEND noninteractive
 
 RUN apt update
-RUN apt -y upgrade
-RUN apt -y install debian-keyring debian-archive-keyring apt-transport-https software-properties-common curl wget gnupg
-
-# https://wiki.ubuntu.com/ToolChain
+RUN apt install -y lsb-release
 RUN echo "deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ $(lsb_release -cs) main restricted universe multiverse" > /etc/apt/sources.list
 RUN echo "deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ $(lsb_release -cs)-updates main restricted universe multiverse" >> /etc/apt/sources.list
 RUN echo "deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ $(lsb_release -cs)-security main restricted universe multiverse" >> /etc/apt/sources.list
-RUN dpkg --add-architecture armhf
 RUN dpkg --add-architecture arm64
-RUN echo "deb [arch=armhf,arm64] http://ports.ubuntu.com/ $(lsb_release -cs) main restricted universe multiverse" >> /etc/apt/sources.list
-RUN echo "deb [arch=armhf,arm64] http://ports.ubuntu.com/ $(lsb_release -cs)-security main restricted universe multiverse" >> /etc/apt/sources.list
-RUN echo "deb [arch=armhf,arm64] http://ports.ubuntu.com/ $(lsb_release -cs)-updates main restricted universe multiverse" >> /etc/apt/sources.list
+RUN echo "deb [arch=arm64] http://ports.ubuntu.com/ $(lsb_release -cs) main restricted universe multiverse" >> /etc/apt/sources.list
+RUN echo "deb [arch=arm64] http://ports.ubuntu.com/ $(lsb_release -cs)-security main restricted universe multiverse" >> /etc/apt/sources.list
+RUN echo "deb [arch=arm64] http://ports.ubuntu.com/ $(lsb_release -cs)-updates main restricted universe multiverse" >> /etc/apt/sources.list
 RUN apt update
 RUN apt -y upgrade
 
-RUN apt -y install zsh git locales locales-all rsync openssh-client sshpass \
-    vim tzdata pwgen zip unzip tree tmux dialog asciidoc doxygen \
-    net-tools dnsutils net-tools iputils-arping iputils-ping telnet \
-    imagemagick ffmpeg fonts-dejavu-extra texlive-full \
-    build-essential cmake pkg-config libtool automake autoconf autoconf-archive binutils cpio mold \
+RUN apt -y install zsh git locales locales-all \
+    vim tzdata zip unzip tree tmux \
+    build-essential crossbuild-essential-arm64 clang lldb lld mold \
+    cmake pkg-config libtool automake autoconf autoconf-archive binutils cpio \
     debhelper bison flex ninja-build \
-    musl-tools musl-dev \
-    crossbuild-essential-armhf crossbuild-essential-arm64 \
-    python3 python3-distutils python3-dev python3-pip virtualenv \
-    php-fpm php-mbstring php-json php-xml php-pear php-bcmath php-curl php-zip \
-    php-mysql php-pgsql php-sqlite3 php-redis php-mongodb php-amqp php-zmq \
-    php-imagick php-gd \
-    nginx rabbitmq-server redis postgresql mariadb-server
-
-# https://launchpad.net/~ubuntu-toolchain-r/+archive/ubuntu/test
-RUN add-apt-repository -y ppa:ubuntu-toolchain-r/test
-RUN apt update
-ENV GCC_VERSION 12
-RUN apt install -y g++-${GCC_VERSION} g++-${GCC_VERSION}-aarch64-linux-gnu g++-${GCC_VERSION}-arm-linux-gnueabihf
-RUN apt install -y libstdc++-${GCC_VERSION}-dev:amd64 libstdc++-${GCC_VERSION}-dev:arm64 libstdc++-${GCC_VERSION}-dev:armhf
-
-# https://apt.llvm.org/
-ENV CLANG_VERSION=15
-RUN echo "deb [arch=amd64] http://apt.llvm.org/$(lsb_release -cs)/ llvm-toolchain-$(lsb_release -cs)-${CLANG_VERSION} main" > /etc/apt/sources.list.d/llvm.list
-RUN wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -
-RUN apt update
-RUN apt install -y clang-${CLANG_VERSION} \
-    clangd-${CLANG_VERSION} clang-tools-${CLANG_VERSION} clang-format-${CLANG_VERSION} \
-    lldb-${CLANG_VERSION} lld-${CLANG_VERSION}
-RUN update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-${CLANG_VERSION} 100
-RUN update-alternatives --install /usr/bin/clang clang /usr/bin/clang-${CLANG_VERSION} 100
-RUN update-alternatives --install /usr/bin/clang-format clang-format /usr/bin/clang-format-${CLANG_VERSION} 100
-RUN update-alternatives --install /usr/bin/lldb lldb /usr/bin/lldb-${CLANG_VERSION} 100
-RUN update-alternatives --install /usr/bin/lld lld /usr/bin/lld-${CLANG_VERSION} 100
-
-# https://www.envoyproxy.io/docs/envoy/latest/start/install#install-envoy-on-ubuntu-linux
-RUN curl -sL 'https://deb.dl.getenvoy.io/public/gpg.8115BA8E629CC074.key' | gpg --dearmor -o /usr/share/keyrings/getenvoy-keyring.gpg
-RUN echo a077cb587a1b622e03aa4bf2f3689de14658a9497a9af2c427bba5f4cc3c4723 /usr/share/keyrings/getenvoy-keyring.gpg | sha256sum --check
-RUN echo "deb [arch=amd64 signed-by=/usr/share/keyrings/getenvoy-keyring.gpg] https://deb.dl.getenvoy.io/public/deb/ubuntu $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/getenvoy.list
-RUN apt update
-RUN apt install -y getenvoy-envoy
-
-# https://www.mongodb.com/docs/manual/tutorial/install-mongodb-on-ubuntu/
-# RUN wget -qO - https://www.mongodb.org/static/pgp/server-6.0.asc | apt-key add -
-# RUN echo "deb [arch=amd64] https://repo.mongodb.org/apt/ubuntu $(lsb_release -cs)/mongodb-org/6.0 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-6.0.list
-# RUN apt update
-# RUN apt install -y mongodb
+    python3 python3-distutils python3-dev python3-pip virtualenv
 
 RUN apt -y autoremove
 RUN apt -y clean
@@ -84,97 +39,15 @@ RUN echo 'export LANG=en_US.UTF-8' >> $HOME/.zshrc
 RUN echo 'export LC_ALL=en_US.UTF-8' >> $HOME/.zshrc
 RUN echo 'export PATH=$HOME/.local/bin:$PATH' >> $HOME/.zshrc
 
-RUN git config --global core.quotepath false
-RUN git config --global http.version HTTP/1.1
-RUN git config --global pull.rebase false
-RUN git config --global url."https://".insteadOf git://
-RUN echo 'set-option -g history-limit 102400' > $HOME/.tmux.conf
-RUN echo 'set-option -g default-shell "/bin/zsh"' >> $HOME/.tmux.conf
-
-RUN zsh -c "source $HOME/.zshrc && pip3 install --user cmake"
-RUN zsh -c "source $HOME/.zshrc \
-    && pip3 install --user ansible paramiko"
-RUN echo 'export ANSIBLE_HOST_KEY_CHECKING=False' >> $HOME/.zshrc
-RUN echo 'alias peony="ANSIBLE_LOG_PATH=$HOME/tmp/$(date +%Y%m%d%H%M%S).log ansible-playbook"' >> $HOME/.zshrc
-
-RUN zsh -c "source $HOME/.zshrc \
-    && pip3 install --user conan \
-    && conan profile new default --detect \
-    && conan profile update settings.compiler.libcxx=libstdc++11 default"
-
-RUN zsh -c "source $HOME/.zshrc && pip3 install --user supervisor"
-
-# https://getcomposer.org/doc/00-intro.md#installation-linux-unix-macos
-RUN wget -q -O $HOME/downloads/composer https://getcomposer.org/installer
-RUN cd $HOME/downloads \
-    && php composer \
-    && mv composer.phar $HOME/.local/bin/composer
-
-# https://github.com/rui314/mold
-# RUN git clone -b v1.6.0 https://github.com/rui314/mold.git $HOME/downloads/mold
-# RUN apt install -y libssl-dev libxxhash-dev zlib1g-dev \
-#     file bsdmainutils
-# RUN zsh -c "source $HOME/.zshrc \
-#     && mkdir $HOME/build/mold \
-#     && cd $HOME/build/mold \
-#     && cmake -DCMAKE_INSTALL_PREFIX=$HOME/.local -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=clang++ $HOME/downloads/mold \
-#     && make -j \
-#     && make install "
-
-# https://github.com/richfelker/musl-cross-make
-RUN git clone https://github.com/richfelker/musl-cross-make.git $HOME/build/musl-cross-make
-RUN cd $HOME/build/musl-cross-make \
-    && echo "TARGET=x86_64-linux-musl" > config.mak \
-    && echo "OUTPUT=/opt/crosstools" >> config.mak \
-    && make \
-    && make install 
-RUN cd $HOME/build/musl-cross-make \
-    && echo "TARGET=aarch64-linux-musl" > config.mak \
-    && echo "OUTPUT=/opt/crosstools" >> config.mak \
-    && make \
-    && make install
-RUN cd $HOME/build/musl-cross-make \
-    && echo "TARGET=arm-linux-musleabihf" > config.mak \
-    && echo "OUTPUT=/opt/crosstools" >> config.mak \
-    && make \
-    && make install
-
-ENV BAZEL_VERSION "v1.15.0"
-RUN wget -q -O $HOME/.local/bin/bazel \
-    https://github.com/bazelbuild/bazelisk/releases/download/${BAZEL_VERSION}/bazelisk-linux-amd64
-RUN chmod +x $HOME/.local/bin/bazel
-
-# https://github.com/rbenv/rbenv
-RUN git clone https://github.com/rbenv/rbenv.git $HOME/.rbenv
-RUN cd $HOME/.rbenv && src/configure && make -C src
-RUN echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> $HOME/.zshrc
-RUN echo 'eval "$(rbenv init -)"' >> $HOME/.zshrc
-RUN git clone https://github.com/rbenv/ruby-build.git $HOME/.rbenv/plugins/ruby-build
-RUN git clone https://github.com/rbenv/rbenv-vars.git $HOME/.rbenv/plugins/rbenv-vars
-ENV RUBY_VERSION "3.1.2"
-RUN apt install -y libssl-dev
-RUN zsh -c "source $HOME/.zshrc \
-    && rbenv install ${RUBY_VERSION} \
-    && rbenv global ${RUBY_VERSION} \
-    && gem install bundler"
-
-ENV GO_VERSION "1.19.2"
-RUN wget -q -P $HOME/downloads https://go.dev/dl/go${GO_VERSION}.linux-amd64.tar.gz
-RUN tar xf $HOME/downloads/go${GO_VERSION}.linux-amd64.tar.gz -C $HOME/local
-RUN echo 'export GOROOT=$HOME/local/go' >> $HOME/.zshrc
-RUN echo 'export PATH=$GOROOT/bin:$PATH' >> $HOME/.zshrc
-RUN echo 'export GOPATH=$HOME/go' >> $HOME/.zshrc
-
-ENV JDK_VERSION "19.0.1-open"
-RUN curl -s "https://get.sdkman.io" | zsh
-RUN sed -i -e 's/sdkman_auto_answer=false/sdkman_auto_answer=true/g' $HOME/.sdkman/etc/config
-RUN zsh -c "source $HOME/.zshrc \
-    && sdk install java ${JDK_VERSION} \
-    && sdk install maven \
-    && sdk install gradle"
+RUN git config --global core.quotepath false \
+    && git config --global http.version HTTP/1.1 \
+    && git config --global pull.rebase false \
+    && git config --global url."https://".insteadOf git://
+RUN echo 'set-option -g history-limit 102400' > $HOME/.tmux.conf \
+    && echo 'set-option -g default-shell "/bin/zsh"' >> $HOME/.tmux.conf
 
 # https://github.com/nvm-sh/nvm
-ENV NVM_VERSION "v0.39.2"
+ENV NVM_VERSION "v0.39.3"
 RUN git clone -b ${NVM_VERSION} https://github.com/nvm-sh/nvm.git $HOME/.nvm
 RUN echo 'export NVM_DIR="$HOME/.nvm"' >> $HOME/.zshrc
 RUN echo '[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"' >> $HOME/.zshrc
@@ -183,47 +56,17 @@ RUN zsh -c "source $HOME/.zshrc \
     && nvm install node \
     && nvm use node \
     && npm i yarn -g"
-RUN zsh -c "source $HOME/.zshrc \
-    && nvm install --lts \
-    && nvm use --lts \
-    && npm i yarn -g"
-# https://stackoverflow.com/questions/37324519/node-sass-does-not-yet-support-your-current-environment-linux-64-bit-with-false
-RUN zsh -c "source $HOME/.zshrc \
-    && nvm install lts/fermium \
-    && nvm use lts/fermium \
-    && npm i yarn -g"
 RUN echo 'export PATH=$HOME/.yarn/bin:$PATH' >> $HOME/.zshrc
 
 # https://www.rust-lang.org/tools/install
 RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
-# https://doc.rust-lang.org/nightly/rustc/platform-support.html
-RUN zsh -c "source $HOME/.cargo/env \
-    && rustup component add rust-analyzer \
-    && rustup target add armv7-unknown-linux-gnueabihf \
-    && rustup target add aarch64-unknown-linux-gnu \
-    && rustup target add x86_64-unknown-linux-musl \
-    && rustup target add aarch64-unknown-linux-musl"
-
-
-RUN apt install -y libpq-dev libmysqlclient-dev libsqlite3-dev
-RUN zsh -c "source $HOME/.zshrc \
-    && cargo install diesel_cli \
-    && cargo install --locked cargo-outdated \
-    && cargo install mdbook"
+RUN zsh -c "source $HOME/.cargo/env && rustup target add aarch64-unknown-linux-gnu"
 
-# https://opensearch.org/downloads.html#opensearch
-ENV OPENSEARCH_VERSION "2.3.0"
-RUN wget -q -P $HOME/downloads \
-    https://artifacts.opensearch.org/releases/bundle/opensearch/${OPENSEARCH_VERSION}/opensearch-${OPENSEARCH_VERSION}-linux-x64.tar.gz
-RUN tar xf $HOME/downloads/opensearch-${OPENSEARCH_VERSION}-linux-x64.tar.gz -C /opt
 
-# https://min.io/download#/linux
-RUN wget -q -O /usr/bin/minio \
-    https://dl.min.io/server/minio/release/linux-amd64/minio
-RUN chmod +x /usr/bin/minio
-
-ENV GRPC_VERSION "v1.50.1"
+# https://github.com/grpc/grpc
+ENV GRPC_VERSION "v1.51.1"
 RUN git clone --recurse-submodules -b $GRPC_VERSION https://github.com/grpc/grpc.git $HOME/downloads/grpc
+RUN apt install -y libssl-dev
 RUN zsh -c "source $HOME/.zshrc \
     && mkdir -pv $HOME/build/grpc \
     && cd $HOME/build/grpc \
@@ -234,77 +77,7 @@ RUN zsh -c "source $HOME/.zshrc \
         -DCMAKE_INSTALL_PREFIX=$HOME/.local $HOME/downloads/grpc \
     && make -j \
     && make install"
-
-# https://github.com/grpc/grpc-web#code-generator-plugin
-ENV GRPC_WEB_PLUGIN_VERSION "1.4.2"
-RUN wget -q -O $HOME/.local/bin/protoc-gen-grpc-web \
-    https://github.com/grpc/grpc-web/releases/download/${GRPC_WEB_PLUGIN_VERSION}/protoc-gen-grpc-web-${GRPC_WEB_PLUGIN_VERSION}-linux-x86_64
-RUN chmod +x $HOME/.local/bin/protoc-gen-grpc-web
-
-# https://github.com/protocolbuffers/protobuf-javascript
-ENV GRPC_JS_PLUGIN_VERSION "3.21.2"
-RUN wget -q -P $HOME/downloads \
-    https://github.com/protocolbuffers/protobuf-javascript/releases/download/v${GRPC_JS_PLUGIN_VERSION}/protobuf-javascript-${GRPC_JS_PLUGIN_VERSION}-linux-x86_64.tar.gz
-RUN mkdir -p $HOME/build/protobuf-javascript \
-    && cd $HOME/build/protobuf-javascript \
-    && tar xf $HOME/downloads/protobuf-javascript-${GRPC_JS_PLUGIN_VERSION}-linux-x86_64.tar.gz \
-    && cp bin/protoc-gen-js $HOME/.local/bin/
-
-# https://repo1.maven.org/maven2/io/grpc/protoc-gen-grpc-java/
-ENV GRPC_JAVA_PLUGIN_VERSION "1.50.2"
-RUN wget -q -O $HOME/.local/bin/grpc_java_plugin \
-    https://repo1.maven.org/maven2/io/grpc/protoc-gen-grpc-java/${GRPC_JAVA_PLUGIN_VERSION}/protoc-gen-grpc-java-${GRPC_JAVA_PLUGIN_VERSION}-linux-x86_64.exe
-RUN chmod +x $HOME/.local/bin/grpc_java_plugin
-
-ENV FLATBUFFERS_VERSION "v22.10.26"
-RUN git clone -b $FLATBUFFERS_VERSION https://github.com/google/flatbuffers.git $HOME/downloads/flatbuffers
-RUN zsh -c "source $HOME/.zshrc \
-    && mkdir -pv $HOME/build/flatbuffers \
-    && cd $HOME/build/flatbuffers \
-    && cmake -DCMAKE_BUILD_TYPE=Release \
-        -DCMAKE_INSTALL_PREFIX=$HOME/.local $HOME/downloads/flatbuffers \
-    && make -j \
-    && make install"
-
-RUN git clone https://github.com/microsoft/vcpkg.git $HOME/local/vcpkg
-RUN $HOME/local/vcpkg/bootstrap-vcpkg.sh
-RUN echo 'export VCPKG_DISABLE_METRICS=1' >> $HOME/.zshrc
-
-ADD conan /opt/conan
-# RUN zsh -c "source $HOME/.zshrc && cd /opt/conan && ./install.sh amd64"
-# RUN zsh -c "source $HOME/.zshrc && cd /opt/conan && ./install.sh arm64"
-# RUN zsh -c "source $HOME/.zshrc && cd /opt/conan && ./install.sh armhf"
-
-# https://opensearch.org/docs/latest/opensearch/install/tar/
-RUN echo "network.host: 0.0.0.0" >> /opt/opensearch-${OPENSEARCH_VERSION}/config/opensearch.yml
-RUN echo "discovery.type: single-node" >> /opt/opensearch-${OPENSEARCH_VERSION}/config/opensearch.yml
-RUN echo "plugins.security.disabled: true" >> /opt/opensearch-${OPENSEARCH_VERSION}/config/opensearch.yml
-RUN chown -R nobody /opt/opensearch-${OPENSEARCH_VERSION}
-
-RUN mkdir -p /var/lib/minio/data
-RUN chown -R nobody /var/lib/minio
-
-RUN sed -i 's/127.0.0.1/0.0.0.0/g' /etc/mysql/mariadb.conf.d/50-server.cnf
-
-RUN su - postgres -c "/usr/lib/postgresql/14/bin/initdb -D /var/lib/postgresql/data"
-RUN echo "listen_addresses = '0.0.0.0'" >> /var/lib/postgresql/data/postgresql.conf
-
-RUN cd /var/lib \
-    && mkdir redis-s redis-1 redis-2 redis-3 redis-4 redis-5 redis-6 \
-    && chown redis:redis redis-s redis-1 redis-2 redis-3 redis-4 redis-5 redis-6 \
-    && chmod 750 redis-s redis-1 redis-2 redis-3 redis-4 redis-5 redis-6
-ADD etc/redis/* /etc/redis/
-
-RUN mkdir /run/php
-RUN echo "<?php phpinfo(); ?>" > /var/www/html/info.php
-RUN echo "daemon off;" >> /etc/nginx/nginx.conf
-ADD etc/nginx.conf /etc/nginx/sites-enabled/default
-
-ADD etc/envoy.yaml /etc/
-
-ADD etc/supervisor /etc/supervisor
-
-
+    
 RUN echo "$(date -u +%4Y%m%d%H%M%S)" | tee /VERSION
 
 VOLUME /workspace

+ 1 - 1
docker/jammy/build.sh

@@ -8,7 +8,7 @@ export CODE="palm-jammy"
 buildah pull ubuntu:jammy
 buildah bud --layers -t $CODE .
 podman save -o $CODE-$VERSION.tar $CODE
-XZ_OPT=-9 tar -cJf - $CODE-$VERSION.tar | split -d -b 1G - $CODE-$VERSION.tar.xz.
+XZ_OPT=-9 tar -cJf $CODE-$VERSION.tar.xz $CODE-$VERSION.tar
 md5sum $CODE-$VERSION.tar* > md5.txt
 
 echo "done($CODE-$VERSION.tar.xz)."

+ 2 - 7
docker/jammy/start.sh

@@ -6,11 +6,6 @@ export NAME="$CODE-$USER"
 if podman container exists $NAME
 then
     podman start -i -a $NAME
-else
-    if [ "$(uname)" == "Darwin" ]
-    then
-        podman run --name $NAME -it --hostname=palm --network host -v $PWD:/workspace:z $CODE
-    else
-        podman run --name $NAME -it --events-backend=file --hostname=palm --network host -v $PWD:/workspace:z $CODE
-    fi
+else    
+    podman run --name $NAME -it --events-backend=file --hostname=palm --network host -v $PWD:/workspace:z $CODE
 fi

+ 316 - 0
docker/spring/Dockerfile

@@ -0,0 +1,316 @@
+FROM ubuntu:latest
+LABEL maintainer="Jeremy Zheng"
+
+ENV DEBIAN_FRONTEND noninteractive
+
+RUN apt update \
+    && apt -y upgrade \
+    && apt -y install debian-keyring debian-archive-keyring apt-transport-https software-properties-common curl wget gnupg
+
+# https://wiki.ubuntu.com/ToolChain
+RUN echo "deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ $(lsb_release -cs) main restricted universe multiverse" > /etc/apt/sources.list
+RUN echo "deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ $(lsb_release -cs)-updates main restricted universe multiverse" >> /etc/apt/sources.list
+RUN echo "deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ $(lsb_release -cs)-security main restricted universe multiverse" >> /etc/apt/sources.list
+RUN dpkg --add-architecture armhf
+RUN dpkg --add-architecture arm64
+RUN echo "deb [arch=armhf,arm64] http://ports.ubuntu.com/ $(lsb_release -cs) main restricted universe multiverse" >> /etc/apt/sources.list
+RUN echo "deb [arch=armhf,arm64] http://ports.ubuntu.com/ $(lsb_release -cs)-security main restricted universe multiverse" >> /etc/apt/sources.list
+RUN echo "deb [arch=armhf,arm64] http://ports.ubuntu.com/ $(lsb_release -cs)-updates main restricted universe multiverse" >> /etc/apt/sources.list
+RUN apt update && apt -y upgrade
+
+RUN apt -y install zsh git locales locales-all rsync openssh-client sshpass \
+    vim tzdata pwgen zip unzip tree tmux dialog asciidoc doxygen \
+    net-tools dnsutils net-tools iputils-arping iputils-ping telnet \
+    imagemagick ffmpeg fonts-dejavu-extra texlive-full \
+    build-essential cmake pkg-config libtool automake autoconf autoconf-archive binutils cpio mold \
+    debhelper bison flex ninja-build \
+    musl-tools musl-dev \
+    crossbuild-essential-armhf crossbuild-essential-arm64 \
+    python3 python3-distutils python3-dev python3-pip virtualenv \
+    php-fpm php-mbstring php-json php-xml php-pear php-bcmath php-curl php-zip \
+    php-mysql php-pgsql php-sqlite3 php-redis php-mongodb php-amqp php-zmq \
+    php-imagick php-gd \
+    nginx rabbitmq-server redis postgresql mariadb-server
+
+# https://launchpad.net/~ubuntu-toolchain-r/+archive/ubuntu/test
+ENV GCC_VERSION 12
+RUN add-apt-repository -y ppa:ubuntu-toolchain-r/test
+RUN apt update
+RUN apt install -y g++-${GCC_VERSION} g++-${GCC_VERSION}-aarch64-linux-gnu g++-${GCC_VERSION}-arm-linux-gnueabihf \
+    libstdc++-${GCC_VERSION}-dev:amd64 libstdc++-${GCC_VERSION}-dev:arm64 libstdc++-${GCC_VERSION}-dev:armhf
+RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-${GCC_VERSION} 100 \
+    && update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-${GCC_VERSION} 100 \
+    && update-alternatives --install /usr/bin/aarch64-linux-gnu-gcc aarch64-linux-gnu-gcc /usr/bin/aarch64-linux-gnu-gcc-${GCC_VERSION} 100 \
+    && update-alternatives --install /usr/bin/aarch64-linux-gnu-g++ aarch64-linux-gnu-g++ /usr/bin/aarch64-linux-gnu-g++-${GCC_VERSION} 100 \
+    && update-alternatives --install /usr/bin/arm-linux-gnueabihf-gcc arm-linux-gnueabihf-gcc /usr/bin/arm-linux-gnueabihf-gcc-${GCC_VERSION} 100 \
+    && update-alternatives --install /usr/bin/arm-linux-gnueabihf-g++ arm-linux-gnueabihf-g++ /usr/bin/arm-linux-gnueabihf-g++-${GCC_VERSION} 100
+
+# https://apt.llvm.org/
+ENV CLANG_VERSION=15
+RUN echo "deb [arch=amd64] http://apt.llvm.org/$(lsb_release -cs)/ llvm-toolchain-$(lsb_release -cs)-${CLANG_VERSION} main" > /etc/apt/sources.list.d/llvm.list
+RUN wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -
+RUN apt update
+RUN apt install -y clang-${CLANG_VERSION} \
+    clangd-${CLANG_VERSION} clang-tools-${CLANG_VERSION} clang-format-${CLANG_VERSION} \
+    lldb-${CLANG_VERSION} lld-${CLANG_VERSION}
+RUN update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-${CLANG_VERSION} 100 \
+    && update-alternatives --install /usr/bin/clang clang /usr/bin/clang-${CLANG_VERSION} 100 \
+    && update-alternatives --install /usr/bin/clang-format clang-format /usr/bin/clang-format-${CLANG_VERSION} 100 \
+    && update-alternatives --install /usr/bin/lldb lldb /usr/bin/lldb-${CLANG_VERSION} 100 \
+    && update-alternatives --install /usr/bin/lld lld /usr/bin/lld-${CLANG_VERSION} 100
+
+# https://www.envoyproxy.io/docs/envoy/latest/start/install#install-envoy-on-ubuntu-linux
+RUN curl -sL 'https://deb.dl.getenvoy.io/public/gpg.8115BA8E629CC074.key' | gpg --dearmor -o /usr/share/keyrings/getenvoy-keyring.gpg
+RUN echo a077cb587a1b622e03aa4bf2f3689de14658a9497a9af2c427bba5f4cc3c4723 /usr/share/keyrings/getenvoy-keyring.gpg | sha256sum --check
+RUN echo "deb [arch=amd64 signed-by=/usr/share/keyrings/getenvoy-keyring.gpg] https://deb.dl.getenvoy.io/public/deb/ubuntu $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/getenvoy.list
+RUN apt update && apt install -y getenvoy-envoy
+
+# https://www.mongodb.com/docs/manual/tutorial/install-mongodb-on-ubuntu/
+# RUN wget -qO - https://www.mongodb.org/static/pgp/server-6.0.asc | apt-key add -
+# RUN echo "deb [arch=amd64] https://repo.mongodb.org/apt/ubuntu $(lsb_release -cs)/mongodb-org/6.0 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-6.0.list
+# RUN apt update
+# RUN apt install -y mongodb
+
+RUN apt -y autoremove && apt -y clean
+
+RUN echo "en_US.UTF-8 UTF-8" > /etc/locale.gen \
+    && locale-gen \
+    && update-locale LANG=en_US.UTF-8
+
+RUN update-alternatives --set editor /usr/bin/vim.basic
+
+RUN mkdir -p $HOME/downloads $HOME/build $HOME/local $HOME/tmp
+
+# https://github.com/ohmyzsh/ohmyzsh
+RUN git clone https://github.com/ohmyzsh/ohmyzsh.git $HOME/.oh-my-zsh
+RUN cp $HOME/.oh-my-zsh/templates/zshrc.zsh-template $HOME/.zshrc
+RUN echo 'export LANG=en_US.UTF-8' >> $HOME/.zshrc \
+    && echo 'export LC_ALL=en_US.UTF-8' >> $HOME/.zshrc \
+    && echo 'export PATH=$HOME/.local/bin:$PATH' >> $HOME/.zshrc
+
+RUN git config --global core.quotepath false \
+    && git config --global http.version HTTP/1.1 \
+    && git config --global pull.rebase false \
+    && git config --global url."https://".insteadOf git://
+RUN echo 'set-option -g history-limit 102400' > $HOME/.tmux.conf \
+    && echo 'set-option -g default-shell "/bin/zsh"' >> $HOME/.tmux.conf
+
+RUN zsh -c "source $HOME/.zshrc && pip3 install --user cmake"
+RUN zsh -c "source $HOME/.zshrc \
+    && pip3 install --user ansible paramiko"
+RUN echo 'export ANSIBLE_HOST_KEY_CHECKING=False' >> $HOME/.zshrc \
+    && echo 'alias peony="ANSIBLE_LOG_PATH=$HOME/tmp/$(date +%Y%m%d%H%M%S).log ansible-playbook"' >> $HOME/.zshrc
+
+RUN zsh -c "source $HOME/.zshrc \
+    && pip3 install --user conan \
+    && conan profile new default --detect \
+    && conan profile update settings.compiler.libcxx=libstdc++11 default"
+
+RUN zsh -c "source $HOME/.zshrc && pip3 install --user supervisor"
+
+# https://getcomposer.org/doc/00-intro.md#installation-linux-unix-macos
+RUN wget -q -O $HOME/downloads/composer https://getcomposer.org/installer
+RUN cd $HOME/downloads \
+    && php composer \
+    && mv composer.phar $HOME/.local/bin/composer
+
+# https://github.com/richfelker/musl-cross-make
+RUN git clone https://github.com/richfelker/musl-cross-make.git $HOME/build/musl-cross-make
+RUN cd $HOME/build/musl-cross-make \
+    && echo "TARGET=x86_64-linux-musl" > config.mak \
+    && echo "OUTPUT=/opt/crosstools" >> config.mak \
+    && make \
+    && make install 
+RUN cd $HOME/build/musl-cross-make \
+    && echo "TARGET=aarch64-linux-musl" > config.mak \
+    && echo "OUTPUT=/opt/crosstools" >> config.mak \
+    && make \
+    && make install
+RUN cd $HOME/build/musl-cross-make \
+    && echo "TARGET=arm-linux-musleabihf" > config.mak \
+    && echo "OUTPUT=/opt/crosstools" >> config.mak \
+    && make \
+    && make install
+RUN echo 'export PATH=/opt/crosstools/bin:$PATH' >> $HOME/.zshrc
+
+# https://github.com/bazelbuild/bazelisk
+ENV BAZEL_VERSION "v1.15.0"
+RUN wget -q -O $HOME/.local/bin/bazel \
+    https://github.com/bazelbuild/bazelisk/releases/download/${BAZEL_VERSION}/bazelisk-linux-amd64
+RUN chmod +x $HOME/.local/bin/bazel
+
+# https://github.com/rbenv/rbenv
+ENV RUBY_VERSION "3.2.0"
+RUN git clone https://github.com/rbenv/rbenv.git $HOME/.rbenv \
+    && git clone https://github.com/rbenv/ruby-build.git $HOME/.rbenv/plugins/ruby-build \
+    && git clone https://github.com/rbenv/rbenv-vars.git $HOME/.rbenv/plugins/rbenv-vars 
+RUN cd $HOME/.rbenv && src/configure && make -C src
+RUN echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> $HOME/.zshrc \
+    && echo 'eval "$(rbenv init -)"' >> $HOME/.zshrc
+# https://github.com/rbenv/ruby-build
+RUN apt install -y libssl-dev libyaml-dev
+RUN zsh -c "source $HOME/.zshrc \
+    && rbenv install ${RUBY_VERSION} \
+    && rbenv global ${RUBY_VERSION} \
+    && gem install bundler"
+RUN zsh -c "source $HOME/.zshrc && rbenv global ${RUBY_VERSION}"
+
+ENV GO_VERSION "1.19.5"
+RUN wget -q -P $HOME/downloads https://go.dev/dl/go${GO_VERSION}.linux-amd64.tar.gz
+RUN tar xf $HOME/downloads/go${GO_VERSION}.linux-amd64.tar.gz -C $HOME/local
+RUN echo 'export GOROOT=$HOME/local/go' >> $HOME/.zshrc \
+    && echo 'export PATH=$GOROOT/bin:$PATH' >> $HOME/.zshrc \
+    && echo 'export GOPATH=$HOME/go' >> $HOME/.zshrc
+
+ENV JDK_VERSION "19.0.1-open"
+RUN curl -s "https://get.sdkman.io" | zsh
+RUN sed -i -e 's/sdkman_auto_answer=false/sdkman_auto_answer=true/g' $HOME/.sdkman/etc/config
+RUN zsh -c "source $HOME/.zshrc \
+    && sdk install java ${JDK_VERSION} \
+    && sdk install maven \
+    && sdk install gradle"
+
+# https://github.com/nvm-sh/nvm
+ENV NVM_VERSION "v0.39.3"
+RUN git clone -b ${NVM_VERSION} https://github.com/nvm-sh/nvm.git $HOME/.nvm
+RUN echo 'export NVM_DIR="$HOME/.nvm"' >> $HOME/.zshrc \
+    && echo '[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"' >> $HOME/.zshrc \
+    && echo '[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"' >> $HOME/.zshrc
+RUN zsh -c "source $HOME/.zshrc \
+    && nvm install node \
+    && nvm use node \
+    && npm i yarn -g"
+RUN zsh -c "source $HOME/.zshrc \
+    && nvm install --lts \
+    && nvm use --lts \
+    && npm i yarn -g"
+# https://stackoverflow.com/questions/37324519/node-sass-does-not-yet-support-your-current-environment-linux-64-bit-with-false
+RUN zsh -c "source $HOME/.zshrc \
+    && nvm install lts/fermium \
+    && nvm use lts/fermium \
+    && npm i yarn -g"
+RUN echo 'export PATH=$HOME/.yarn/bin:$PATH' >> $HOME/.zshrc
+
+# https://www.rust-lang.org/tools/install
+RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
+# https://doc.rust-lang.org/nightly/rustc/platform-support.html
+RUN zsh -c "source $HOME/.cargo/env \
+    && rustup component add rust-analyzer \
+    && rustup target add armv7-unknown-linux-gnueabihf \
+    && rustup target add aarch64-unknown-linux-gnu \
+    && rustup target add x86_64-unknown-linux-musl \
+    && rustup target add aarch64-unknown-linux-musl"
+
+
+RUN apt install -y libpq-dev libmysqlclient-dev libsqlite3-dev
+RUN zsh -c "source $HOME/.zshrc \
+    && cargo install diesel_cli \
+    && cargo install --locked cargo-outdated \
+    && cargo install mdbook"
+
+# https://opensearch.org/downloads.html#opensearch
+ENV OPENSEARCH_VERSION "2.4.1"
+RUN wget -q -P $HOME/downloads \
+    https://artifacts.opensearch.org/releases/bundle/opensearch/${OPENSEARCH_VERSION}/opensearch-${OPENSEARCH_VERSION}-linux-x64.tar.gz
+RUN tar xf $HOME/downloads/opensearch-${OPENSEARCH_VERSION}-linux-x64.tar.gz -C /opt
+
+# https://min.io/download#/linux
+RUN wget -q -O /usr/bin/minio \
+    https://dl.min.io/server/minio/release/linux-amd64/minio
+RUN chmod +x /usr/bin/minio
+
+# https://github.com/grpc/grpc
+ENV GRPC_VERSION "v1.51.1"
+RUN git clone --recurse-submodules -b $GRPC_VERSION https://github.com/grpc/grpc.git $HOME/downloads/grpc
+# ENV PROTOBUF_VERSION "v3.21.8"
+# RUN cd $HOME/downloads/grpc/third_party/protobuf \
+#     && git checkout ${PROTOBUF_VERSION} \
+#     && git submodule update --init --recursive
+RUN zsh -c "source $HOME/.zshrc \
+    && mkdir -pv $HOME/build/grpc \
+    && cd $HOME/build/grpc \
+    && cmake -DCMAKE_BUILD_TYPE=Release \
+        -DgRPC_INSTALL=ON \
+        -DgRPC_SSL_PROVIDER=package \
+        -DgRPC_BUILD_TESTS=OFF \
+        -DCMAKE_INSTALL_PREFIX=$HOME/.local $HOME/downloads/grpc \
+    && make -j \
+    && make install"
+
+# https://github.com/grpc/grpc-web#code-generator-plugin
+ENV GRPC_WEB_PLUGIN_VERSION "1.4.2"
+RUN wget -q -O $HOME/.local/bin/protoc-gen-grpc-web \
+    https://github.com/grpc/grpc-web/releases/download/${GRPC_WEB_PLUGIN_VERSION}/protoc-gen-grpc-web-${GRPC_WEB_PLUGIN_VERSION}-linux-x86_64
+RUN chmod +x $HOME/.local/bin/protoc-gen-grpc-web
+
+# https://github.com/protocolbuffers/protobuf-javascript
+ENV GRPC_JS_PLUGIN_VERSION "3.21.2"
+RUN wget -q -P $HOME/downloads \
+    https://github.com/protocolbuffers/protobuf-javascript/releases/download/v${GRPC_JS_PLUGIN_VERSION}/protobuf-javascript-${GRPC_JS_PLUGIN_VERSION}-linux-x86_64.tar.gz
+RUN mkdir -p $HOME/build/protobuf-javascript \
+    && cd $HOME/build/protobuf-javascript \
+    && tar xf $HOME/downloads/protobuf-javascript-${GRPC_JS_PLUGIN_VERSION}-linux-x86_64.tar.gz \
+    && cp bin/protoc-gen-js $HOME/.local/bin/
+
+# https://repo1.maven.org/maven2/io/grpc/protoc-gen-grpc-java/
+ENV GRPC_JAVA_PLUGIN_VERSION "1.52.1"
+RUN wget -q -O $HOME/.local/bin/grpc_java_plugin \
+    https://repo1.maven.org/maven2/io/grpc/protoc-gen-grpc-java/${GRPC_JAVA_PLUGIN_VERSION}/protoc-gen-grpc-java-${GRPC_JAVA_PLUGIN_VERSION}-linux-x86_64.exe
+RUN chmod +x $HOME/.local/bin/grpc_java_plugin
+
+# https://github.com/google/flatbuffers
+ENV FLATBUFFERS_VERSION "v23.1.4"
+RUN git clone -b $FLATBUFFERS_VERSION https://github.com/google/flatbuffers.git $HOME/downloads/flatbuffers
+RUN zsh -c "source $HOME/.zshrc \
+    && mkdir -pv $HOME/build/flatbuffers \
+    && cd $HOME/build/flatbuffers \
+    && cmake -DCMAKE_BUILD_TYPE=Release \
+        -DCMAKE_INSTALL_PREFIX=$HOME/.local $HOME/downloads/flatbuffers \
+    && make -j \
+    && make install"
+
+# https://github.com/microsoft/vcpkg
+RUN git clone https://github.com/microsoft/vcpkg.git $HOME/local/vcpkg
+RUN $HOME/local/vcpkg/bootstrap-vcpkg.sh \
+    && echo 'export VCPKG_DISABLE_METRICS=1' >> $HOME/.zshrc
+
+ADD conan /opt/conan
+# RUN zsh -c "source $HOME/.zshrc && cd /opt/conan && ./install.sh amd64"
+# RUN zsh -c "source $HOME/.zshrc && cd /opt/conan && ./install.sh arm64"
+# RUN zsh -c "source $HOME/.zshrc && cd /opt/conan && ./install.sh armhf"
+
+# https://opensearch.org/docs/latest/opensearch/install/tar/
+RUN echo "network.host: 0.0.0.0" >> /opt/opensearch-${OPENSEARCH_VERSION}/config/opensearch.yml \
+    && echo "discovery.type: single-node" >> /opt/opensearch-${OPENSEARCH_VERSION}/config/opensearch.yml \
+    && echo "plugins.security.disabled: true" >> /opt/opensearch-${OPENSEARCH_VERSION}/config/opensearch.yml \
+    && chown -R nobody /opt/opensearch-${OPENSEARCH_VERSION}
+
+RUN mkdir -p /var/lib/minio/data \
+    && chown -R nobody /var/lib/minio
+
+RUN sed -i 's/127.0.0.1/0.0.0.0/g' /etc/mysql/mariadb.conf.d/50-server.cnf
+
+RUN su - postgres -c "/usr/lib/postgresql/14/bin/initdb -D /var/lib/postgresql/data"
+RUN echo "listen_addresses = '0.0.0.0'" >> /var/lib/postgresql/data/postgresql.conf \
+    && echo "host  all  all 0.0.0.0/0 md5" >> /var/lib/postgresql/data/pg_hba.conf
+
+ADD etc/redis/* /etc/redis/
+RUN cd /var/lib \
+    && mkdir redis-s redis-1 redis-2 redis-3 redis-4 redis-5 redis-6 \
+    && chown redis:redis redis-s redis-1 redis-2 redis-3 redis-4 redis-5 redis-6 \
+    && chmod 750 redis-s redis-1 redis-2 redis-3 redis-4 redis-5 redis-6
+
+RUN mkdir /run/php \
+    && echo "<?php phpinfo(); ?>" > /var/www/html/info.php \
+    && echo "daemon off;" >> /etc/nginx/nginx.conf
+ADD etc/nginx.conf /etc/nginx/sites-enabled/default
+
+ADD etc/envoy.yaml /etc/
+ADD etc/supervisor /etc/supervisor
+
+RUN echo "$(date -u +%4Y%m%d%H%M%S)" | tee /VERSION
+
+VOLUME /workspace
+WORKDIR /workspace
+
+CMD ["/bin/zsh", "-l"]

+ 63 - 0
docker/spring/README.md

@@ -0,0 +1,63 @@
+# USAGE
+
+- add to `/etc/sysctl.d/60-my.conf` and then `reboot` or `sysctl -p`
+
+  ```text
+  vm.overcommit_memory = 1
+  vm.max_map_count = 262144
+  ```
+
+- start container [dashboard](http://localhost:10001)
+
+  ```bash
+  $ cd ~/workspace
+  $ ./saturn-xiv/palm/docker/spring/start.sh
+  > supervisord -c /etc/supervisor/supervisord.conf
+  # init redis cluster
+  > /etc/redis/clusters-init.sh
+  ```
+
+- PostgreSql
+
+  ```bash
+  psql -h 127.0.0.1 -p 5432 -U postgres
+  ```
+
+- MySql
+
+  ```bash
+  # reset root's password
+  mysql_secure_installation
+  ```
+
+- Redis
+
+  ```bash
+  # connect to redis node-1
+  redis-cli -c -h 127.0.0.1 -p 16371
+  ```
+
+- Minio [dashboard](http://localhost:9001) (`admin:12345678`)
+
+- RabbitMQ [dashboard](http://localhost:15672) (`guest:guest`)
+
+  ```bash
+  # enable rabbitmq management plugin
+  rabbitmq-plugins enable rabbitmq_management
+  ```
+
+- Php [info.php](http://localhost:8080/info.php)
+
+- OpenSearch
+
+  ```bash
+  # show info
+  curl -X GET http://localhost:9200
+  curl -X GET http://localhost:9200/_cat/plugins?v
+  ```
+
+- Vcpkg
+
+  ```bash
+  $HOME/local/vcpkg/vcpkg upgrade --no-dry-run
+  ```

+ 16 - 0
docker/spring/build.sh

@@ -0,0 +1,16 @@
+#!/bin/bash
+
+set -e
+
+export VERSION=$(date "+%4Y%m%d%H%M%S")
+export CODE="palm-spring"
+
+buildah pull ubuntu:latest
+buildah bud --layers -t $CODE .
+podman save -o $CODE-$VERSION.tar $CODE
+XZ_OPT=-9 tar -cJf - $CODE-$VERSION.tar | split -d -b 3G - $CODE-$VERSION.tar.xz.
+md5sum $CODE-$VERSION.tar* > md5.txt
+
+echo "done($CODE-$VERSION.tar.xz)."
+
+exit 0

+ 0 - 0
docker/jammy/conan/conanfile.txt → docker/spring/conan/conanfile.txt


+ 0 - 0
docker/jammy/conan/install.sh → docker/spring/conan/install.sh


+ 0 - 0
docker/jammy/conan/profiles/amd64 → docker/spring/conan/profiles/amd64


+ 0 - 0
docker/jammy/conan/profiles/arm64 → docker/spring/conan/profiles/arm64


+ 0 - 0
docker/jammy/conan/profiles/armhf → docker/spring/conan/profiles/armhf


+ 0 - 0
docker/jammy/conan/toolchains/amd64.cmake → docker/spring/conan/toolchains/amd64.cmake


+ 0 - 0
docker/jammy/conan/toolchains/arm64.cmake → docker/spring/conan/toolchains/arm64.cmake


+ 0 - 0
docker/jammy/conan/toolchains/armhf.cmake → docker/spring/conan/toolchains/armhf.cmake


+ 0 - 0
docker/jammy/etc/envoy.yaml → docker/spring/etc/envoy.yaml


+ 1 - 0
docker/jammy/etc/nginx.conf → docker/spring/etc/nginx.conf

@@ -18,3 +18,4 @@ server {
         fastcgi_pass unix:/run/php/php8.1-fpm.sock;
     }
 }
+

+ 0 - 0
docker/jammy/etc/redis/clusters-init.sh → docker/spring/etc/redis/clusters-init.sh


+ 0 - 0
docker/jammy/etc/redis/node-1.conf → docker/spring/etc/redis/node-1.conf


+ 0 - 0
docker/jammy/etc/redis/node-2.conf → docker/spring/etc/redis/node-2.conf


+ 0 - 0
docker/jammy/etc/redis/node-3.conf → docker/spring/etc/redis/node-3.conf


+ 0 - 0
docker/jammy/etc/redis/node-4.conf → docker/spring/etc/redis/node-4.conf


+ 0 - 0
docker/jammy/etc/redis/node-5.conf → docker/spring/etc/redis/node-5.conf


+ 0 - 0
docker/jammy/etc/redis/node-6.conf → docker/spring/etc/redis/node-6.conf


+ 0 - 0
docker/jammy/etc/redis/node-s.conf → docker/spring/etc/redis/node-s.conf


+ 0 - 0
docker/jammy/etc/supervisor/conf.d/envoy.conf → docker/spring/etc/supervisor/conf.d/envoy.conf


+ 0 - 0
docker/jammy/etc/supervisor/conf.d/minio.conf → docker/spring/etc/supervisor/conf.d/minio.conf


+ 0 - 0
docker/jammy/etc/supervisor/conf.d/mysql.conf → docker/spring/etc/supervisor/conf.d/mysql.conf


+ 0 - 0
docker/jammy/etc/supervisor/conf.d/nginx.conf → docker/spring/etc/supervisor/conf.d/nginx.conf


+ 0 - 0
docker/jammy/etc/supervisor/conf.d/opensearch.conf → docker/spring/etc/supervisor/conf.d/opensearch.conf


+ 0 - 0
docker/jammy/etc/supervisor/conf.d/php-fpm.conf → docker/spring/etc/supervisor/conf.d/php-fpm.conf


+ 0 - 0
docker/jammy/etc/supervisor/conf.d/postgresql.conf → docker/spring/etc/supervisor/conf.d/postgresql.conf


+ 0 - 0
docker/jammy/etc/supervisor/conf.d/rabbitmq.conf → docker/spring/etc/supervisor/conf.d/rabbitmq.conf


+ 0 - 0
docker/jammy/etc/supervisor/conf.d/redis.conf → docker/spring/etc/supervisor/conf.d/redis.conf


+ 0 - 0
docker/jammy/etc/supervisor/supervisord.conf → docker/spring/etc/supervisor/supervisord.conf


+ 11 - 0
docker/spring/start.sh

@@ -0,0 +1,11 @@
+#!/bin/bash
+
+export CODE="palm-spring"
+export NAME="$CODE-$USER"
+
+if podman container exists $NAME
+then
+    podman start -i -a $NAME
+else    
+    podman run --name $NAME -it --events-backend=file --hostname=palm --network host -v $PWD:/workspace:z $CODE
+fi

+ 28 - 0
scripts/dashboard/deploy.sh

@@ -0,0 +1,28 @@
+#!/bin/bash
+
+set -e
+
+if [ "$#" -ne 1 ]
+then
+    echo "USAGE: $0 DOMAIN"
+    exit 1
+fi
+
+export GIT_VERSION=$(git describe --tags --always --dirty --first-parent)
+
+
+if [ ! -d node_modules ]
+then
+    yarn install
+fi
+
+PUBLIC_URL=/pcd yarn build
+
+
+echo "$GIT_VERSION" > build/VERSION
+echo "$(date -R)" >> build/VERSION
+
+
+rsync -rzv build/ deploy@$1:/var/www/$1/dashboard
+
+echo "done($GIT_VERSION)."

+ 11 - 0
scripts/dashboard/pack.sh

@@ -0,0 +1,11 @@
+#!/bin/sh
+
+set -e
+
+export VERSION=$(date "+%4Y%m%d%H%M%S")
+
+XZ_OPT=-9 tar -cJf dashboard-$VERSION.tar.xz node_modules yarn.lock
+
+echo "Done($VERSION)."
+
+exit 0

+ 97 - 0
scripts/dashboard/third.sh

@@ -0,0 +1,97 @@
+#!/bin/bash
+
+set -e
+
+install_oauth() {
+    yarn add @react-oauth/google@latest react-facebook-login
+}
+
+install_react() {
+    yarn add filesize dayjs timezones-list grpc-web \
+        moment moment-timezone date-fns \
+        marked @types/marked \
+        diff @types/diff \
+        lodash @types/lodash \
+        @fortawesome/fontawesome-free \
+        famfamfam-flags famfamfam-silk famfamfam-mini \
+        google-protobuf @types/google-protobuf \
+        js-cookie @types/js-cookie \
+        mermaid \
+        jwt-decode dinero.js@alpha \
+        video.js @types/video.js \
+        react-copy-to-clipboard @types/react-copy-to-clipboard \
+        react-quill react-dropzone \
+        google-map-react qrcode.react \
+        react-markdown @uiw/react-md-editor \
+        react-color @types/react-color \
+        react-pdf @types/react-pdf \
+        react-json-view react-syntax-highlighter \
+        emoji-mart react-sparklines react-highlight-words \
+        react-number-format react-image-crop \
+        react-player \
+        react-draggable \
+        react-big-calendar @types/react-big-calendar \
+        react-intl \
+        react-router-dom@latest \
+        react-helmet-async \
+        formik yup \
+        @reduxjs/toolkit react-redux
+
+}
+
+# https://ant.design/docs/react/getting-started
+install_ant_design() {
+    yarn add antd @ant-design/pro-components @ant-design/charts
+}
+
+# https://developer.microsoft.com/en-us/fluentui#/get-started/web
+install_fluent_ui(){
+    yarn add @fluentui/react
+}
+
+# https://mui.com/material-ui/getting-started/overview/
+install_material_design() {
+    yarn add @mui/material @emotion/react @emotion/styled \
+        @mui/icons-material @fontsource/roboto \
+        @mui/x-date-pickers
+}
+
+# https://react-bootstrap.github.io/getting-started/introduction
+install_bootstrap() {
+    yarn add react-bootstrap bootstrap
+}
+
+
+if [ "$#" -ne 1 ]
+then
+    echo "USAGE: $0 material|fluent|antd|bootstrap"
+    exit 1
+fi
+
+# yarn add @originjs/vite-plugin-commonjs --dev
+
+if [ $1 == "material" ]
+then
+    install_react
+    install_material_design
+elif [ $1 == "antd" ]
+then
+    install_react
+    install_ant_design
+elif [ $1 == "fluent" ]
+then
+    install_react
+    install_fluent_ui
+elif [ $1 == "bootstrap" ]
+then
+    install_react
+    install_bootstrap
+else
+    echo "unknown option $1"
+    exit 1
+fi
+
+
+echo "Done($1)."
+
+exit 0

+ 25 - 0
scripts/ops/hugo.sh

@@ -0,0 +1,25 @@
+#!/bin/bash
+
+set -e
+
+if [ "$#" -ne 2 ]
+then
+  echo "USAGE: $0 DOMAIN REPO"
+  exit 1
+fi
+
+export WORKSPACE=/var/www/$1
+
+if [ ! -d $WORKSPACE/repo.git ]
+then
+  git clone $2 $WORKSPACE/repo.git
+fi
+
+cd $WORKSPACE/repo.git
+git pull
+git submodule update --init --recursive
+hugo -d $WORKSPACE/htdocs
+
+echo "done."
+exit 0
+

+ 5 - 0
scripts/ops/minio/README.md

@@ -0,0 +1,5 @@
+# USAGE
+
+```bash
+sudo ./setup.sh change-me.com
+```

+ 98 - 0
scripts/ops/minio/setup.sh

@@ -0,0 +1,98 @@
+#!/bin/bash
+
+set -e
+
+if [ "$#" -ne 1 ]
+then
+    echo "USAGE: $0 DOMAIN"
+    exit 1
+fi
+
+echo "check /var/lib/minio"
+if [ ! -d /var/lib/minio ]
+then
+    mkdir /var/lib/minio
+    chown www-data:www-data /var/lib/minio
+    chmod 700 /var/lib/minio
+fi
+
+echo "check /lib/systemd/system/minio.service"
+if [ ! -f /lib/systemd/system/minio.service ]
+then
+    cat > /lib/systemd/system/minio.service <<EOF
+[Unit]
+Description=MinIO offers high-performance, S3 compatible object storage.
+After=network.target
+
+[Service]
+Type=simple
+User=www-data
+Group=www-data
+WorkingDirectory=/var/lib/minio
+ExecStart=/usr/bin/minio server data
+Restart=always
+RestartSec=10s
+
+Environment="MINIO_ADDRESS=127.0.0.1:9000"
+Environment="MINIO_CONSOLE_ADDRESS=127.0.0.1:9001"
+Environment="MINIO_ROOT_USER=www"
+Environment="MINIO_ROOT_PASSWORD=$(pwgen 32 1)"
+
+[Install]
+WantedBy=multi-user.target
+EOF
+    chmod 444 /lib/systemd/system/minio.service
+    systemctl daemon-reload
+    systemctl enable minio
+fi
+
+
+echo "check /etc/nginx/sites-enabled/s3.$1.conf"
+if [ ! -f /etc/nginx/sites-enabled/s3.$1.conf ]
+then
+
+    cat > /etc/nginx/sites-enabled/s3.$1.conf <<EOF
+server {
+  server_name assets.$1;
+  access_log /var/log/nginx/assets.$1.access.log;
+  error_log  /var/log/nginx/assets.$1.error.log;
+
+  location / {
+    proxy_set_header X-Forwarded-Proto http;
+    proxy_set_header X-Real-IP \$remote_addr;
+    proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;    
+    proxy_set_header Host \$http_host;
+    proxy_redirect off;
+    proxy_pass http://127.0.0.1:9000;
+    proxy_set_header Upgrade \$http_upgrade;
+    proxy_set_header Connection "upgrade";
+  }
+}
+
+server {
+
+  server_name s3.$1;
+  access_log /var/log/nginx/s3.$1.access.log;
+  error_log  /var/log/nginx/s3.$1.error.log;
+
+  location / {
+    proxy_set_header X-Forwarded-Proto http;
+    proxy_set_header X-Real-IP \$remote_addr;
+    proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;    
+    proxy_set_header Host \$http_host;
+    proxy_redirect off;
+    proxy_pass http://127.0.0.1:9001;
+    proxy_set_header Upgrade \$http_upgrade;
+    proxy_set_header Connection "upgrade";
+  }
+}
+
+EOF
+    chmod 644 /etc/nginx/sites-enabled/s3.$1.conf
+fi
+
+echo "done($1)."
+exit 0
+
+
+

+ 5 - 0
scripts/ops/nginx/README.md

@@ -0,0 +1,5 @@
+# USAGE
+
+```bash
+sudo ./react.sh change-me.com 8080
+```

+ 58 - 0
scripts/ops/nginx/react.sh

@@ -0,0 +1,58 @@
+#!/bin/bash
+
+set -e
+
+
+if [ "$#" -ne 2 ]
+then
+    echo "USAGE: $0 DOMAIN PORT"
+    exit 1
+fi
+
+echo "check /etc/nginx/sites-enabled/$1.conf"
+if [ ! -f /etc/nginx/sites-enabled/$1.conf ]
+then
+    cat > /etc/nginx/sites-enabled/$1.conf <<EOF
+server {
+
+  server_name $1;
+  access_log /var/log/nginx/$1.access.log;
+  error_log  /var/log/nginx/$1.error.log;
+
+  gzip on;
+  gzip_comp_level 9;
+  gzip_min_length 1k;
+  gzip_types text/plain text/css application/xml application/javascript;
+  gzip_vary on;
+  client_max_body_size 128M;
+  
+
+  location /my/ {
+    alias /var/www/$1/current/dashboard/;
+    try_files \$uri \$uri/ /my/index.html;
+    
+    location ~* \\.(css|js|png|jpg|jpeg|gif|gz|svg|mp4|ogg|ogv|webm|htc|xml|woff)\$ {
+      access_log off;
+      expires max;
+    }
+  }
+  
+  location / {
+    proxy_set_header X-Forwarded-Proto http;
+    proxy_set_header X-Real-IP \$remote_addr;
+    proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;    
+    proxy_set_header Host \$http_host;
+    proxy_redirect off;
+    proxy_pass http://127.0.0.1:$2;
+    proxy_set_header Upgrade \$http_upgrade;
+    proxy_set_header Connection "upgrade";
+  }
+
+}
+EOF
+
+    chmod 644 /etc/nginx/sites-enabled/$1.conf
+fi
+
+echo "done($1)."
+exit 0

+ 16 - 0
scripts/ops/redis/README.md

@@ -0,0 +1,16 @@
+# Redis
+
+## Cluster init
+
+- create node 1
+
+```bash
+sudo ./setup.sh 1
+sudo systemctl start redis-node-1
+```
+
+- create cluster
+
+```bash
+sudo redis-cli --cluster create 127.0.0.1:6371 127.0.0.1:6372 127.0.0.1:6373 127.0.0.1:6374 127.0.0.1:6375 127.0.0.1:6376
+```

+ 74 - 0
scripts/ops/redis/setup.sh

@@ -0,0 +1,74 @@
+#!/bin/bash
+
+set -e
+
+
+if [ "$#" -ne 1 ]
+then
+    echo "USAGE: $0 NODE_ID"
+    exit 1
+fi
+
+echo "check /etc/redis/node-$1.conf"
+if [ ! -d /etc/redis ]
+then
+    mkdir -p /etc/redis
+fi
+
+if [ ! -f /etc/redis/node-$1.conf ]
+then
+    cat > /etc/redis/node-$1.conf <<EOF
+bind 0.0.0.0
+port 637${1}
+daemonize no
+dir /var/lib/redis-node-$1
+
+cluster-enabled yes
+cluster-config-file /tmp/redis-node-$1.conf
+cluster-node-timeout 5000
+
+appendonly yes
+appendfsync everysec
+EOF
+    chown redis:redis /etc/redis/node-$1.conf
+    chmod 400 /etc/redis/node-$1.conf
+fi
+
+echo "create /var/lib/redis-node-$1"
+if [ ! -d /var/lib/redis-node-$1 ]
+then
+    mkdir -p /var/lib/redis-node-$1
+    chown redis:redis /var/lib/redis-node-$1
+    chmod 700 /var/lib/redis-node-$1
+fi
+
+echo "create /lib/systemd/system/redis-node-$1.service"
+if [ ! -f /lib/systemd/system/redis-node-$1.service ]
+then
+
+    cat > /lib/systemd/system/redis-node-$1.service <<EOF
+[Unit]
+Description=Redis cluster node-$1
+After=network.target
+
+[Service]
+Type=simple
+User=redis
+Group=redis
+WorkingDirectory=/var/lib/redis-node-$1
+ExecStart=/usr/bin/redis-server /etc/redis/node-$1.conf
+# or always, on-abort, on-failure, etc
+Restart=always 
+RestartSec=10s
+
+[Install]
+WantedBy=multi-user.target
+EOF
+    chmod 444 /lib/systemd/system/redis-node-$1.service
+    systemctl daemon-reload
+    systemctl enable redis-node-$1
+fi
+
+echo "done."
+
+exit 0

+ 18 - 0
scripts/spring/README.md

@@ -0,0 +1,18 @@
+# SPRING
+
+- [Install VirtualBox](https://www.virtualbox.org/wiki/Downloads)
+- [Install Vagrant](https://developer.hashicorp.com/vagrant/downloads)
+- Usage(**RUN IN the spring FOLDER**)
+
+  ```bash
+  # start virtual machine
+  VAGRANT_EXPERIMENTAL="disks" vagrant up --provider=virtualbox
+  # list boxes
+  vagrant box list
+  # ssh login to the virtual machine
+  vagrant ssh
+  # shutdown the virtual machine
+  vagrant halt
+  # show virtualbox machines
+  vagrant status
+  ```

+ 74 - 0
scripts/spring/Vagrantfile

@@ -0,0 +1,74 @@
+# -*- mode: ruby -*-
+# vi: set ft=ruby :
+
+# All Vagrant configuration is done below. The "2" in Vagrant.configure
+# configures the configuration version (we support older styles for
+# backwards compatibility). Please don't change it unless you know what
+# you're doing.
+Vagrant.configure("2") do |config|
+  # The most common configuration options are documented and commented below.
+  # For a complete reference, please see the online documentation at
+  # https://docs.vagrantup.com.
+
+  config.vm.disk :disk, size: "500GB", primary: true
+
+  # Every Vagrant development environment requires a box. You can search for
+  # boxes at https://vagrantcloud.com/search.
+  config.vm.box = "ubuntu/jammy64"
+  config.vm.box_version = "20221219.0.0"
+
+  # Disable automatic box update checking. If you disable this, then
+  # boxes will only be checked for updates when the user runs
+  # `vagrant box outdated`. This is not recommended.
+  # config.vm.box_check_update = false
+
+  # Create a forwarded port mapping which allows access to a specific port
+  # within the machine from a port on the host machine. In the example below,
+  # accessing "localhost:8080" will access port 80 on the guest machine.
+  # NOTE: This will enable public access to the opened port
+  # config.vm.network "forwarded_port", guest: 80, host: 8080
+
+  # Create a forwarded port mapping which allows access to a specific port
+  # within the machine from a port on the host machine and only allow access
+  # via 127.0.0.1 to disable public access
+  # config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1"
+
+  # Create a private network, which allows host-only access to the machine
+  # using a specific IP.
+  # config.vm.network "private_network", ip: "192.168.33.10"
+
+  # Create a public network, which generally matched to bridged network.
+  # Bridged networks make the machine appear as another physical device on
+  # your network.
+  config.vm.network "public_network"
+
+  # Share an additional folder to the guest VM. The first argument is
+  # the path on the host to the actual folder. The second argument is
+  # the path on the guest to mount the folder. And the optional third
+  # argument is a set of non-required options.
+  # config.vm.synced_folder "..", "/var/www/localhost"
+
+  # Provider-specific configuration so you can fine-tune various
+  # backing providers for Vagrant. These expose provider-specific options.
+  # Example for VirtualBox:
+  #
+  config.vm.provider "virtualbox" do |vb|
+    # Display the VirtualBox GUI when booting the machine
+    vb.gui = false
+  
+    # Customize the amount of memory on the VM:
+    vb.memory = "12288"
+    vb.cpus = 8
+  end
+  #
+  # View the documentation for the provider you are using for more
+  # information on available options.
+
+  # Enable provisioning with a shell script. Additional provisioners such as
+  # Ansible, Chef, Docker, Puppet and Salt are also available. Please see the
+  # documentation for more information about their specific syntax and use.
+  config.vm.provision "shell", inline: <<-SHELL
+    apt update
+    apt -y upgrade
+  SHELL
+end

+ 7 - 0
scripts/spring/user/README.md

@@ -0,0 +1,7 @@
+# User
+
+## dashboard@nginx
+
+```bash
+BUILD_PATH=/srv/http/$USER/dashboard yarn build
+```

+ 34 - 17
scripts/spring/user/create.sh

@@ -8,14 +8,14 @@ then
     exit 1
 fi
 
-apt -y install zsh git zip unzip bzip2 curl wget vim pwgen
+pacman -S --needed zsh git zip unzip bzip2 curl wget vim pwgen
 
 if id "$1" &>/dev/null
 then
     echo "user $1 found"
 else
     echo "create user $1"
-    useradd -m -d /workspace/home/$1 -s /bin/zsh $1
+    useradd -m -d /home/$1 -s /bin/zsh $1
 fi
 
 echo 'reset password'
@@ -23,42 +23,49 @@ passwd -l $1
 echo "$1:$(pwgen 32 1)" | chpasswd
 
 echo 'setup nginx'
+export WORKSPACE=/srv/http/$1
 
-if [ ! -d /workspace/www/$1/htdocs ]
+if [ ! -d $WORKSPACE/htdocs ]
 then
-    mkdir -p /workspace/www/$1/htdocs
-    chown $1:$1 /workspace/www/$1/htdocs
+    mkdir -p $WORKSPACE/htdocs
+    chown $1:$1 $WORKSPACE/htdocs
 fi
 
-if [ ! -d /workspace/www/$1/logs ]
+if [ ! -d $WORKSPACE/logs ]
 then
-    mkdir -p /workspace/www/$1/logs
-    chown www-data:www-data /workspace/www/$1/logs
+    mkdir -p $WORKSPACE/logs
+    chown http:http $WORKSPACE/logs
 fi
 
-if [ ! -d /workspace/www/$1/tmp ]
+if [ ! -d $WORKSPACE/tmp ]
 then
     mkdir -p /workspace/tmp/$1
     chown $1:$1 /workspace/tmp/$1
 fi
 
-if [ ! -f /workspace/www/$1/nginx.conf ]
+if [ ! -d $WORKSPACE/dashboard ]
+then
+    mkdir -p /workspace/dashboard/$1
+    chown $1:$1 /workspace/dashboard/$1
+fi
+
+if [ ! -f $WORKSPACE/nginx.conf ]
 then
     # https://en.wikipedia.org/wiki/Hostname#Restrictions_on_valid_host_names
-    cat > /workspace/www/$1/nginx.conf <<EOF
+    cat > $WORKSPACE/nginx.conf <<EOF
 # https://laravel.com/docs/9.x/deployment#nginx
 
 server {
-  listen 80;
+  listen 60080;
   server_name ${1//_/-}.spring.wikipali.org;
 
-  access_log /workspace/www/$1/logs/access.org;
-  error_log /workspace/www/$1/logs/error.log;
+  access_log $WORKSPACE/logs/access.org;
+  error_log $WORKSPACE/logs/error.log;
 
   add_header X-Frame-Options "SAMEORIGIN";
   add_header X-Content-Type-Options "nosniff";
 
-  root /workspace/www/$1/htdocs/public;
+  root $WORKSPACE/htdocs/public;
   index index.html index.php;
 
   charset utf-8;
@@ -69,12 +76,22 @@ server {
     try_files \$uri \$uri/ /index.php?\$query_string;
   }
 
+  location /my/ {
+    alias $WORKSPACE/dashboard/;
+    try_files \$uri \$uri/ /my/index.html;
+    
+    location ~* \.(css|js|png|jpg|jpeg|gif|gz|svg|mp4|ogg|ogv|webm|htc|xml|woff)$ {
+      access_log off;
+      expires max;
+    }
+  }
+
   location = /favicon.ico { access_log off; log_not_found off; }
   location = /robots.txt  { access_log off; log_not_found off; }
   error_page 404 /index.php;
   
   location ~ \.php\$ {
-    fastcgi_pass unix:/run/php/php-fpm.sock;
+    fastcgi_pass unix:/run/php-fpm/php-fpm.sock;
     fastcgi_param SCRIPT_FILENAME \$realpath_root\$fastcgi_script_name;
     include fastcgi_params;
   }
@@ -84,7 +101,7 @@ server {
 }
 EOF
 
-ln -sf /workspace/www/$1/nginx.conf /etc/nginx/sites-enabled/$1.spring.wikipali.org.conf
+ln -sf $WORKSPACE/nginx.conf /etc/nginx/sites-enabled/$1-spring.conf
 
 fi
 

+ 41 - 27
scripts/spring/user/setup.sh

@@ -5,7 +5,8 @@ set -e
 echo 'setup zsh'
 if [ ! -d "$HOME/.oh-my-zsh" ]
 then
-    git clone https://github.com/ohmyzsh/ohmyzsh.git $HOME/.oh-my-zsh
+    # git clone https://github.com/ohmyzsh/ohmyzsh.git $HOME/.oh-my-zsh
+    tar xf ohmyzsh.tar.xz -C $HOME
 fi
 if [ ! -f "$HOME/.zshrc" ]
 then
@@ -16,7 +17,8 @@ fi
 echo 'setup nodejs'
 if [ ! -d "$HOME/.nvm" ]
 then
-    git clone https://github.com/nvm-sh/nvm.git $HOME/.nvm
+    # git clone https://github.com/nvm-sh/nvm.git $HOME/.nvm
+    tar xf nvm.tar.xz -C $HOME
 
     cat >> $HOME/.profile <<EOF
 export NVM_DIR="\$HOME/.nvm"
@@ -24,31 +26,38 @@ export NVM_DIR="\$HOME/.nvm"
 [ -s "\$NVM_DIR/bash_completion" ] && \. "\$NVM_DIR/bash_completion" 
 EOF
     echo 'export PATH=$HOME/.yarn/bin:$PATH' >> $HOME/.profile
+    echo 'export EDITOR=vim' >> $HOME/.profile
+
+    echo 'export http_proxy=socks5h://0:8000' >> $HOME/.profile
+    echo 'export https_proxy=socks5h://0:8000' >> $HOME/.profile
+    echo 'export ftp_proxy=socks5h://0:8000' >> $HOME/.profile
+    
+    echo 'export PATH=$HOME/.local/bin:$PATH' >> $HOME/.profile
 fi
 
-cd $HOME/.nvm
-git checkout v0.39.2
-. $HOME/.nvm/nvm.sh
+# cd $HOME/.nvm
+# git checkout v0.39.3
+# . $HOME/.nvm/nvm.sh
 
-if ! [ -x "$(command -v yarn)" ]
-then
-    nvm install node 
-    nvm use node 
-    npm install yarn -g
-fi
+# if ! [ -x "$(command -v yarn)" ]
+# then
+#     nvm install node 
+#     nvm use node 
+#     npm install yarn -g
+# fi
 
-mkdir -p $HOME/.local/bin $HOME/local $HOME/downloads
+mkdir -p $HOME/.local/bin $HOME/local $HOME/downloads $HOME/tmp $HOME/workspace
 
 echo 'setup php'
-if [ ! -f "$HOME/downloads/composer" ]
-then
-    wget -O $HOME/downloads/composer https://getcomposer.org/installer
-fi
+# if [ ! -f "$HOME/downloads/composer" ]
+# then
+#     wget -O $HOME/downloads/composer https://getcomposer.org/installer
+# fi
 if [ ! -f "$HOME/.local/bin/composer" ]
 then
-    cd $HOME/downloads
-    php composer
-    mv composer.phar $HOME/.local/bin/composer
+    # cd $HOME/downloads
+    # php composer
+    cp composer.phar $HOME/.local/bin/composer
 fi
 
 echo 'setup ssh'
@@ -56,20 +65,24 @@ if [ ! -d $HOME/.ssh ]
 then
     mkdir $HOME/.ssh
     chmod 700 $HOME/.ssh
-    cat /tmp/$USER.pub > $HOME/.ssh/authorized_keys
+    cat $USER.pub > $HOME/.ssh/authorized_keys    
 fi
 
+echo 'setup vnc'
+mkdir -p $HOME/.vnc
+cat > $HOME/.vnc/xstartup <<EOF
+#!/bin/sh
+
+unset SESSION_MANAGER
+exec openbox-session &
+startlxqt &
+EOF
+
 
 echo 'setup workspace folder'
 if [ ! -L $HOME/www ]
 then
-    ln -sf /workspace/www/$USER $HOME/www
-fi
-
-echo 'setup tmp folder'
-if [ ! -L $HOME/tmp ]
-then
-    ln -sf /workspace/tmp/$USER $HOME/tmp
+    ln -sf /srv/http/$USER $HOME/www
 fi
 
 echo 'setup tmux'
@@ -83,6 +96,7 @@ echo 'setup git'
 git config --global core.quotepath false
 git config --global http.version HTTP/1.1
 git config --global pull.rebase false
+git config --global http.proxy socks5h://0:8000
 
 echo "done."