Initial commit: 50 shell-script generators with web UI
- 8 categories / 50 generators covering middleware, databases, runtimes, systemd services, system tools, network, monitoring, security - VNC supports XFCE / GNOME / KDE Plasma / MATE / LXQt desktops - Node.js versions 18-26 (incl. current LTS 24 Krypton and current 26) - Live preview, copy / download / multi-script bundle in web UI - Distro-aware (Ubuntu/Debian/CentOS/RHEL/Rocky/Alma/Fedora) - All 50 generators pass bash -n syntax check - Zero pip dependencies (Flask stdlib only)
This commit is contained in:
@@ -0,0 +1,212 @@
|
||||
"""
|
||||
Extra databases (Memcached, SQLite, Elasticsearch, ClickHouse).
|
||||
"""
|
||||
from . import register, Generator, Field
|
||||
from . import bash_header, quote, bool_str, yes
|
||||
|
||||
|
||||
# ========================== Memcached ==========================
|
||||
class Memcached(Generator):
|
||||
id = "memcached"
|
||||
title = "Memcached"
|
||||
category = "databases"
|
||||
icon = "🧠"
|
||||
tags = ["memcached", "cache"]
|
||||
description = "安装 memcached 并配置监听地址/内存限制/连接数。"
|
||||
fields = [
|
||||
Field("port", "端口", "number", default="11211", min_=1, max_=65535),
|
||||
Field("memory_mb", "最大内存 (MB)", "number", default="256"),
|
||||
Field("max_connections", "最大连接数", "number", default="1024"),
|
||||
Field("listen", "监听地址", "text", default="0.0.0.0"),
|
||||
]
|
||||
|
||||
def render(self, p):
|
||||
port = str(p.get("port", "11211"))
|
||||
mem = str(p.get("memory_mb", "256"))
|
||||
conn = str(p.get("max_connections", "1024"))
|
||||
listen = p.get("listen", "0.0.0.0")
|
||||
out = [bash_header(self.title)]
|
||||
out.append('log "Installing memcached..."')
|
||||
out.append('$PKG_INSTALL memcached')
|
||||
out.append('cp /etc/memcached.conf /etc/memcached.conf.bak.$(date +%s) || true')
|
||||
out.append('sed -i "s/^-m .*/-m ' + mem + '/" /etc/memcached.conf')
|
||||
out.append('sed -i "s/^-p .*/-p ' + port + '/" /etc/memcached.conf')
|
||||
out.append('sed -i "s/^-l .*/-l ' + listen + '/" /etc/memcached.conf')
|
||||
out.append('sed -i "s/^-c .*/-c ' + conn + '/" /etc/memcached.conf')
|
||||
out.append('systemctl enable --now memcached')
|
||||
out.append('echo "stats" | nc -q1 127.0.0.1 ' + port + ' | head -5')
|
||||
return "\n".join(out) + "\n"
|
||||
|
||||
|
||||
# ========================== SQLite3 (system tools, no server) ==========================
|
||||
class SqliteTools(Generator):
|
||||
id = "sqlite"
|
||||
title = "SQLite 命令行工具"
|
||||
category = "databases"
|
||||
icon = "📁"
|
||||
tags = ["sqlite"]
|
||||
description = "安装最新版 sqlite3 + sqlite-utils。"
|
||||
fields = [
|
||||
Field("install_python_bindings", "安装 Python sqlite-utils", "checkbox", default="yes"),
|
||||
]
|
||||
|
||||
def render(self, p):
|
||||
pyb = bool_str(p.get("install_python_bindings", True))
|
||||
out = [bash_header(self.title)]
|
||||
out.append('log "Installing sqlite3..."')
|
||||
out.append('$PKG_INSTALL sqlite3 libsqlite3-dev || $PKG_INSTALL sqlite sqlite-devel')
|
||||
if pyb:
|
||||
out.append('command -v pip3 >/dev/null || $PKG_INSTALL python3-pip')
|
||||
out.append('pip3 install --break-system-packages sqlite-utils || pip3 install sqlite-utils')
|
||||
out.append('sqlite3 --version')
|
||||
return "\n".join(out) + "\n"
|
||||
|
||||
|
||||
# ========================== Elasticsearch ==========================
|
||||
class Elasticsearch(Generator):
|
||||
id = "elasticsearch"
|
||||
title = "Elasticsearch"
|
||||
category = "databases"
|
||||
icon = "🔍"
|
||||
tags = ["elasticsearch", "es", "search"]
|
||||
description = "安装 Elasticsearch (单节点开发模式)。"
|
||||
warnings = [
|
||||
"ES JVM 默认 1G,小内存机器请调小 -Xms -Xmx。",
|
||||
"生产环境必须设置 xpack.security.enabled=true。",
|
||||
]
|
||||
fields = [
|
||||
Field("version", "版本", "select", default="8.13.4",
|
||||
options=["7.17.20", "8.11.4", "8.13.4", "8.14.3"]),
|
||||
Field("port", "HTTP 端口", "number", default="9200", min_=1, max_=65535),
|
||||
Field("jvm_heap", "JVM 堆", "text", default="1g"),
|
||||
Field("discovery", "discovery.type", "select", default="single-node",
|
||||
options=["single-node"]),
|
||||
Field("enable_security", "启用 xpack security", "checkbox", default="no"),
|
||||
]
|
||||
|
||||
def render(self, p):
|
||||
ver = p.get("version", "8.13.4")
|
||||
port = str(p.get("port", "9200"))
|
||||
heap = p.get("jvm_heap", "1g")
|
||||
sec = bool_str(p.get("enable_security"))
|
||||
out = [bash_header(self.title)]
|
||||
out.append('log "Installing Elasticsearch ' + ver + '..."')
|
||||
out.append('useradd -r -s /bin/false elasticsearch 2>/dev/null || true')
|
||||
out.append('cd /tmp')
|
||||
out.append('curl -fsSL -O https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-' + ver + '-linux-x86_64.tar.gz')
|
||||
out.append('rm -rf /opt/elasticsearch')
|
||||
out.append('tar -xzf elasticsearch-' + ver + '-linux-x86_64.tar.gz -C /opt/')
|
||||
out.append('mv /opt/elasticsearch-' + ver + ' /opt/elasticsearch')
|
||||
out.append('rm -f elasticsearch-' + ver + '-linux-x86_64.tar.gz')
|
||||
out.append('chown -R elasticsearch:elasticsearch /opt/elasticsearch')
|
||||
out.append('sed -i "s/^-Xms.*/-Xms' + heap + '/" /opt/elasticsearch/config/jvm.options')
|
||||
out.append('sed -i "s/^-Xmx.*/-Xmx' + heap + '/" /opt/elasticsearch/config/jvm.options')
|
||||
out.append('sed -i "s/^#http.port.*/http.port: ' + port + '/" /opt/elasticsearch/config/elasticsearch.yml')
|
||||
out.append('echo "discovery.type: single-node" >> /opt/elasticsearch/config/elasticsearch.yml')
|
||||
out.append('echo "network.host: 0.0.0.0" >> /opt/elasticsearch/config/elasticsearch.yml')
|
||||
out.append('echo "xpack.security.enabled: ' + ('true' if sec else 'false') + '" >> /opt/elasticsearch/config/elasticsearch.yml')
|
||||
out.append('cat > /etc/systemd/system/elasticsearch.service <<UNIT_EOF\n'
|
||||
'[Unit]\nDescription=Elasticsearch\nAfter=network.target\n\n'
|
||||
'[Service]\nType=simple\n'
|
||||
'User=elasticsearch\nGroup=elasticsearch\n'
|
||||
'LimitNOFILE=65536\n'
|
||||
'Environment=ES_HOME=/opt/elasticsearch\n'
|
||||
'Environment=ES_PATH_CONF=/opt/elasticsearch/config\n'
|
||||
'ExecStart=/opt/elasticsearch/bin/elasticsearch\n'
|
||||
'Restart=on-failure\n\n'
|
||||
'[Install]\nWantedBy=multi-user.target\nUNIT_EOF')
|
||||
out.append('systemctl daemon-reload')
|
||||
out.append('systemctl enable --now elasticsearch')
|
||||
out.append('log "Wait ~30s then: curl http://127.0.0.1:' + port + '"')
|
||||
return "\n".join(out) + "\n"
|
||||
|
||||
|
||||
# ========================== ClickHouse ==========================
|
||||
class ClickHouse(Generator):
|
||||
id = "clickhouse"
|
||||
title = "ClickHouse"
|
||||
category = "databases"
|
||||
icon = "🏛️"
|
||||
tags = ["clickhouse", "olap", "columnar"]
|
||||
description = "安装 ClickHouse 服务端 + 客户端。"
|
||||
fields = [
|
||||
Field("tcp_port", "TCP 端口", "number", default="9000"),
|
||||
Field("http_port", "HTTP 端口", "number", default="8123"),
|
||||
Field("listen_host", "Listen host", "text", default="0.0.0.0"),
|
||||
Field("data_path", "数据目录", "text", default="/var/lib/clickhouse"),
|
||||
]
|
||||
|
||||
def render(self, p):
|
||||
tcp = str(p.get("tcp_port", "9000"))
|
||||
http = str(p.get("http_port", "8123"))
|
||||
lh = p.get("listen_host", "0.0.0.0")
|
||||
dp = p.get("data_path", "/var/lib/clickhouse")
|
||||
out = [bash_header(self.title)]
|
||||
out.append('log "Installing ClickHouse..."')
|
||||
out.append('$PKG_INSTALL apt-transport-https ca-certificates curl || $PKG_INSTALL ca-certificates curl')
|
||||
out.append('mkdir -p /etc/apt/keyrings')
|
||||
out.append('curl -fsSL https://clickhouse.com/keys/clickhouse.asc | gpg --dearmor -o /etc/apt/keyrings/clickhouse.gpg')
|
||||
out.append('echo "deb [signed-by=/etc/apt/keyrings/clickhouse.gpg] https://packages.clickhouse.com/deb stable main" > /etc/apt/sources.list.d/clickhouse.list')
|
||||
out.append('apt-get update')
|
||||
out.append('DEBIAN_FRONTEND=noninteractive apt-get install -y clickhouse-server clickhouse-client')
|
||||
out.append('mkdir -p ' + dp)
|
||||
out.append('chown -R clickhouse:clickhouse ' + dp)
|
||||
out.append('sed -i "s|<tcp_port>.*</tcp_port>|<tcp_port>' + tcp + '</tcp_port>|" /etc/clickhouse-server/config.xml')
|
||||
out.append('sed -i "s|<http_port>.*</http_port>|<http_port>' + http + '</http_port>|" /etc/clickhouse-server/config.xml')
|
||||
out.append('sed -i "s|<listen_host>.*</listen_host>|<listen_host>' + lh + '</listen_host>|" /etc/clickhouse-server/config.xml')
|
||||
out.append('sed -i "s|<path>.*</path>|<path>' + dp + '</path>|" /etc/clickhouse-server/config.xml')
|
||||
out.append('systemctl enable --now clickhouse-server')
|
||||
out.append('sleep 3')
|
||||
out.append('clickhouse-client -q "SELECT version()"')
|
||||
return "\n".join(out) + "\n"
|
||||
|
||||
|
||||
# ========================== Consul (service mesh) ==========================
|
||||
class Consul(Generator):
|
||||
id = "consul"
|
||||
title = "HashiCorp Consul"
|
||||
category = "middleware"
|
||||
icon = "🌐"
|
||||
tags = ["consul", "service-discovery"]
|
||||
description = "安装 Consul 单节点开发模式。"
|
||||
fields = [
|
||||
Field("version", "Consul 版本", "text", default="1.18.1"),
|
||||
Field("datacenter", "Datacenter", "text", default="dc1"),
|
||||
Field("ui", "启用 Web UI", "checkbox", default="yes"),
|
||||
]
|
||||
|
||||
def render(self, p):
|
||||
ver = p.get("version", "1.18.1")
|
||||
dc = p.get("datacenter", "dc1")
|
||||
ui = bool_str(p.get("ui", True))
|
||||
out = [bash_header(self.title)]
|
||||
out.append('useradd -r -s /bin/false consul 2>/dev/null || true')
|
||||
out.append('mkdir -p /etc/consul.d /var/lib/consul')
|
||||
out.append('cd /tmp')
|
||||
out.append('curl -fsSL -O https://releases.hashicorp.com/consul/' + ver + '/consul_' + ver + '_linux_amd64.zip')
|
||||
out.append('unzip -o consul_' + ver + '_linux_amd64.zip -d /usr/local/bin/')
|
||||
out.append('rm -f consul_' + ver + '_linux_amd64.zip')
|
||||
out.append('chown -R consul:consul /etc/consul.d /var/lib/consul')
|
||||
out.append('cat > /etc/consul.d/consul.hcl <<CFG_EOF\n'
|
||||
'datacenter = "' + dc + '"\n'
|
||||
'data_dir = "/var/lib/consul"\n'
|
||||
'client_addr = "0.0.0.0"\n'
|
||||
'ui_config { enabled = ' + ('true' if ui else 'false') + ' }\n'
|
||||
'server = true\n'
|
||||
'bootstrap_expect = 1\n'
|
||||
'CFG_EOF')
|
||||
out.append('cat > /etc/systemd/system/consul.service <<UNIT_EOF\n'
|
||||
'[Unit]\nDescription=HashiCorp Consul\nAfter=network.target\n\n'
|
||||
'[Service]\nType=simple\nUser=consul\nGroup=consul\n'
|
||||
'ExecStart=/usr/local/bin/consul agent -config-dir=/etc/consul.d/\n'
|
||||
'Restart=on-failure\nLimitNOFILE=65536\n\n'
|
||||
'[Install]\nWantedBy=multi-user.target\nUNIT_EOF')
|
||||
out.append('systemctl daemon-reload')
|
||||
out.append('systemctl enable --now consul')
|
||||
out.append('sleep 3')
|
||||
out.append('consul members || true')
|
||||
return "\n".join(out) + "\n"
|
||||
|
||||
|
||||
for _g in [Memcached, SqliteTools, Elasticsearch, ClickHouse, Consul]:
|
||||
register(_g())
|
||||
Reference in New Issue
Block a user