| #!/usr/bin/env lua |
| |
| local script_path = debug.getinfo(1).source:sub(2) |
| |
| local function trim(s) |
| return (s:gsub("^%s*(.-)%s*$", "%1")) |
| end |
| |
| local function excute_cmd(cmd) |
| local t = io.popen(cmd) |
| local data = t:read("*all") |
| t:close() |
| return data |
| end |
| |
| local pwd = trim(excute_cmd("pwd")) |
| if not pwd then |
| error("failed to fetch current path") |
| end |
| |
| excute_cmd("install -d -m 777 /tmp/apisix_cores/") |
| |
| local apisix_home = "/usr/local/apisix" |
| if script_path:sub(1, 4) == '/usr' or script_path:sub(1, 4) == '/bin' then |
| package.cpath = "/usr/local/apisix/deps/lib64/lua/5.1/?.so;" |
| .. "/usr/local/apisix/deps/lib/lua/5.1/?.so;" |
| .. package.cpath |
| |
| package.path = "/usr/local/apisix/deps/share/lua/5.1/apisix/lua/?.lua;" |
| .. "/usr/local/apisix/deps/share/lua/5.1/?.lua;" |
| .. "/usr/share/lua/5.1/apisix/lua/?.lua;" |
| .. "/usr/local/share/lua/5.1/apisix/lua/?.lua;" |
| .. package.path |
| |
| else |
| apisix_home = pwd |
| package.cpath = pwd .. "/deps/lib64/lua/5.1/?.so;" |
| .. package.cpath |
| |
| package.path = pwd .. "/lua/?.lua;" |
| .. pwd .. "/deps/share/lua/5.1/?.lua;" |
| .. package.path |
| end |
| -- print("apisix_home: ", apisix_home) |
| |
| do |
| local ok, json = pcall(require, "cjson") |
| if ok and json then |
| io.stderr:write("please remove the cjson library in Lua, it may " |
| .. "conflict with the cjson library in openresty. " |
| .. "\n luarocks remove cjson\n") |
| return |
| end |
| end |
| |
| local yaml = require("apisix.core.yaml") |
| local template = require("resty.template") |
| |
| local ngx_tpl = [=[ |
| master_process on; |
| |
| worker_processes auto; |
| {% if os_name == "Linux" then %} |
| worker_cpu_affinity auto; |
| {% end %} |
| |
| error_log logs/error.log error; |
| pid logs/nginx.pid; |
| |
| worker_rlimit_nofile 20480; |
| |
| events { |
| accept_mutex off; |
| worker_connections 10620; |
| } |
| |
| worker_rlimit_core 500M; |
| working_directory /tmp/apisix_cores/; |
| |
| worker_shutdown_timeout 3; |
| |
| http { |
| lua_package_path "$prefix/deps/share/lua/5.1/?.lua;]=] |
| .. [=[{*apisix_lua_home*}/lua/?.lua;;{*lua_path*};"; |
| lua_package_cpath "$prefix/deps/lib64/lua/5.1/?.so;]=] |
| .. [=[$prefix/deps/lib/lua/5.1/?.so;;]=] |
| .. [=[{*lua_cpath*};"; |
| |
| lua_shared_dict plugin-limit-req 10m; |
| lua_shared_dict plugin-limit-count 10m; |
| lua_shared_dict prometheus-metrics 10m; |
| lua_shared_dict plugin-limit-conn 10m; |
| lua_shared_dict upstream-healthcheck 10m; |
| lua_shared_dict worker-events 10m; |
| |
| lua_ssl_verify_depth 5; |
| ssl_session_timeout 86400; |
| |
| lua_socket_log_errors off; |
| |
| resolver ipv6=off local=on; |
| resolver_timeout 5; |
| |
| lua_http10_buffering off; |
| |
| lua_regex_match_limit 100000; |
| lua_regex_cache_max_entries 8192; |
| |
| log_format main '$remote_addr - $remote_user [$time_local] $http_host "$request" $status $body_bytes_sent $request_time "$http_referer" "$http_user_agent" $upstream_addr $upstream_status $upstream_response_time'; |
| |
| access_log logs/access.log main buffer=32768 flush=3; |
| open_file_cache max=1000 inactive=60; |
| client_max_body_size 0; |
| |
| server_tokens off; |
| more_set_headers 'Server: APISIX web server'; |
| |
| include mime.types; |
| |
| real_ip_header {* real_ip_header *}; |
| {% for _, real_ip in ipairs(real_ip_from) do %} |
| set_real_ip_from {{real_ip}}; |
| {% end %} |
| |
| upstream apisix_backend { |
| server 0.0.0.1; |
| balancer_by_lua_block { |
| apisix.http_balancer_phase() |
| } |
| |
| keepalive 32; |
| } |
| |
| init_by_lua_block { |
| require "resty.core" |
| apisix = require("apisix") |
| apisix.http_init() |
| } |
| |
| init_worker_by_lua_block { |
| apisix.http_init_worker() |
| } |
| |
| {% if enable_admin and port_admin then %} |
| server { |
| listen {* port_admin *}; |
| |
| location /apisix/admin { |
| {% for _, allow_ip in ipairs(allow_admin) do %} |
| allow {*allow_ip*}; |
| {% end %} |
| deny all; |
| |
| content_by_lua_block { |
| apisix.http_admin() |
| } |
| } |
| } |
| {% end %} |
| |
| server { |
| listen {* node_listen *}; |
| listen {* node_ssl_listen *} ssl; |
| ssl_certificate cert/apisix.crt; |
| ssl_certificate_key cert/apisix.key; |
| ssl_session_cache shared:SSL:1m; |
| |
| {% if with_module_status then %} |
| location = /apisix/nginx_status { |
| allow 127.0.0.0/24; |
| deny all; |
| access_log off; |
| stub_status; |
| } |
| {% end %} |
| |
| {% if enable_admin and not port_admin then %} |
| location /apisix/admin { |
| {% for _, allow_ip in ipairs(allow_admin) do %} |
| allow {*allow_ip*}; |
| {% end %} |
| deny all; |
| |
| content_by_lua_block { |
| apisix.http_admin() |
| } |
| } |
| {% end %} |
| |
| ssl_certificate_by_lua_block { |
| apisix.http_ssl_phase() |
| } |
| |
| location /apisix/dashboard { |
| index index.html; |
| {% for _, allow_ip in ipairs(allow_admin) do %} |
| allow {*allow_ip*}; |
| {% end %} |
| deny all; |
| |
| root ../; |
| |
| proxy_set_header X-Real-IP $remote_addr; |
| proxy_set_header X-Real-PORT $remote_port; |
| proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; |
| |
| try_files $uri $uri/ /index.html; |
| } |
| |
| location / { |
| set $upstream_scheme 'http'; |
| set $upstream_host $host; |
| set $upstream_upgrade ''; |
| set $upstream_connection ''; |
| set $upstream_uri ''; |
| |
| access_by_lua_block { |
| apisix.http_access_phase() |
| } |
| |
| proxy_http_version 1.1; |
| proxy_set_header Host $upstream_host; |
| proxy_set_header Upgrade $upstream_upgrade; |
| proxy_set_header Connection $upstream_connection; |
| proxy_set_header X-Real-IP $remote_addr; |
| proxy_pass_header Server; |
| proxy_pass_header Date; |
| proxy_pass $upstream_scheme://apisix_backend$upstream_uri; |
| |
| header_filter_by_lua_block { |
| apisix.http_header_filter_phase() |
| } |
| |
| log_by_lua_block { |
| apisix.http_log_phase() |
| } |
| } |
| } |
| } |
| ]=] |
| |
| local function write_file(file_path, data) |
| local file = io.open(file_path, "w+") |
| if not file then |
| return false, "failed to open file: " .. file_path |
| end |
| |
| file:write(data) |
| file:close() |
| return true |
| end |
| |
| local function read_file(file_path) |
| local file = io.open(file_path, "rb") |
| if not file then |
| return false, "failed to open file: " .. file_path |
| end |
| |
| local data = file:read("*all") |
| file:close() |
| return data |
| end |
| |
| local function exec(command) |
| local t= io.popen(command) |
| local res = t:read("*all") |
| t:close() |
| return trim(res) |
| end |
| |
| local function read_yaml_conf() |
| local ymal_conf, err = read_file(apisix_home .. "/conf/config.yaml") |
| if not ymal_conf then |
| return nil, err |
| end |
| |
| return yaml.parse(ymal_conf) |
| end |
| |
| local function get_openresty_version() |
| local str = "nginx version: openresty/" |
| local ret = excute_cmd("openresty -v 2>&1") |
| local pos = string.find(ret,str) |
| if pos ~= 1 then |
| return nil |
| end |
| |
| return string.sub(ret,string.len(str)+1) |
| end |
| |
| local function split(self, sep) |
| local sep, fields = sep or ":", {} |
| local pattern = string.format("([^%s]+)", sep) |
| self:gsub(pattern, function(c) fields[#fields + 1] = c end) |
| return fields |
| end |
| |
| local function check_or_version(cur_ver_s, need_ver_s) |
| local cur_vers = split(cur_ver_s, [[.]]) |
| local need_vers = split(need_ver_s, [[.]]) |
| local len = math.max(#cur_vers, #need_vers) |
| |
| for i = 1, len do |
| local cur_ver = tonumber(cur_vers[i]) or 0 |
| local need_ver = tonumber(need_vers[i]) or 0 |
| if cur_ver > need_ver then |
| return true |
| end |
| |
| if cur_ver < need_ver then |
| return false |
| end |
| end |
| |
| return true |
| end |
| |
| local _M = {version = 0.1} |
| |
| function _M.help() |
| print([[ |
| Usage: apisix [action] <argument> |
| |
| help: show this message, then exit |
| init: initialize the local nginx.conf |
| init_etcd: initialize the data of etcd |
| start: start the apisix server |
| stop: stop the apisix server |
| reload: reload the apisix server |
| ]]) |
| end |
| |
| local function init() |
| -- read_yaml_conf |
| local yaml_conf, err = read_yaml_conf() |
| if not yaml_conf then |
| error("failed to read local yaml config of apisix: " .. err) |
| end |
| -- print("etcd: ", yaml_conf.etcd.host) |
| |
| local or_ver = excute_cmd("openresty -V 2>&1") |
| local with_module_status = true |
| if or_ver and not or_ver:find("http_stub_status_module", 1, true) then |
| io.stderr:write("'http_stub_status_module' module is missing in ", |
| "your openresty, please check it out. Without this ", |
| "module, there will be fewer monitoring indicators.\n") |
| with_module_status = false |
| end |
| |
| -- -- Using template.render |
| local sys_conf = { |
| lua_path = package.path, |
| lua_cpath = package.cpath, |
| os_name = exec("uname"), |
| apisix_lua_home = apisix_home, |
| with_module_status = with_module_status, |
| node_ssl_listen = 9443, -- default value |
| } |
| for k,v in pairs(yaml_conf.apisix) do |
| sys_conf[k] = v |
| end |
| |
| local conf_render = template.compile(ngx_tpl) |
| local ngxconf = conf_render(sys_conf) |
| |
| local ok, err = write_file(apisix_home .. "/conf/nginx.conf", ngxconf) |
| if not ok then |
| error("failed to update nginx.conf: " .. err) |
| end |
| |
| local op_ver = get_openresty_version() |
| if op_ver == nil then |
| io.stderr:write("can not find openresty\n") |
| return |
| end |
| |
| local need_ver = "1.15.8" |
| if not check_or_version(op_ver, need_ver) then |
| io.stderr:write("openresty version must >=", need_ver, "\n") |
| return |
| end |
| end |
| _M.init = init |
| |
| local function init_etcd(show_output) |
| -- read_yaml_conf |
| local yaml_conf, err = read_yaml_conf() |
| if not yaml_conf then |
| error("failed to read local yaml config of apisix: " .. err) |
| end |
| |
| local etcd_conf = yaml_conf.etcd |
| local uri = etcd_conf.host .. "/v2/keys" .. (etcd_conf.prefix or "") |
| |
| local timeout = etcd_conf.timeout or 1 |
| |
| for _, dir_name in ipairs({"/routes", "/upstreams", "/services", |
| "/plugins", "/consumers", "/node_status", |
| "/ssl"}) do |
| local cmd = "curl " .. uri .. dir_name |
| .. "?prev_exist=false -X PUT -d dir=true " |
| .. "--connect-timeout " .. timeout |
| .. " --max-time " .. timeout * 2 .. " --retry 1 2>&1" |
| |
| local res = exec(cmd) |
| if not res:find("index", 1, true) |
| and not res:find("createdIndex", 1, true) then |
| error(cmd .. "\n" .. res) |
| end |
| |
| if show_output then |
| print(cmd) |
| print(res) |
| end |
| end |
| end |
| _M.init_etcd = init_etcd |
| |
| local openresty_args = [[openresty -p ]] .. apisix_home .. [[ -c ]] |
| .. apisix_home .. [[/conf/nginx.conf]] |
| |
| function _M.start(...) |
| init(...) |
| init_etcd(...) |
| |
| local cmd = openresty_args |
| -- print(cmd) |
| os.execute(cmd) |
| end |
| |
| function _M.stop() |
| local cmd = openresty_args .. [[ -s stop]] |
| -- print(cmd) |
| os.execute(cmd) |
| end |
| |
| function _M.reload() |
| local test_cmd = openresty_args .. [[ -t -q ]] |
| if os.execute((test_cmd)) ~= 0 then |
| return |
| end |
| |
| local cmd = openresty_args .. [[ -s reload]] |
| -- print(cmd) |
| os.execute(cmd) |
| end |
| |
| local cmd_action = arg[1] |
| if not cmd_action then |
| return _M.help() |
| end |
| |
| if not _M[cmd_action] then |
| print("invalid argument: ", cmd_action, "\n") |
| return |
| end |
| |
| _M[cmd_action](arg[2]) |