2 * nghttp2 - HTTP/2 C Library
4 * Copyright (c) 2012 Tatsuhiro Tsujikawa
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 #include <sys/types.h>
30 #ifdef HAVE_SYS_SOCKET_H
31 # include <sys/socket.h>
32 #endif // HAVE_SYS_SOCKET_H
36 #endif // HAVE_NETDB_H
38 #ifdef HAVE_NETINET_IN_H
39 # include <netinet/in.h>
40 #endif // HAVE_NETINET_IN_H
41 #include <netinet/tcp.h>
42 #ifdef HAVE_ARPA_INET_H
43 # include <arpa/inet.h>
44 #endif // HAVE_ARPA_INET_H
47 #endif // HAVE_UNISTD_H
51 #endif // HAVE_SYSLOG_H
54 #endif // HAVE_LIMITS_H
55 #ifdef HAVE_SYS_TIME_H
56 # include <sys/time.h>
57 #endif // HAVE_SYS_TIME_H
58 #include <sys/resource.h>
59 #ifdef HAVE_LIBSYSTEMD
60 # include <systemd/sd-daemon.h>
61 #endif // HAVE_LIBSYSTEMD
69 #include <initializer_list>
72 #include <openssl/ssl.h>
73 #include <openssl/err.h>
76 #include <nghttp2/nghttp2.h>
78 #include "shrpx_config.h"
79 #include "shrpx_tls.h"
80 #include "shrpx_log_config.h"
81 #include "shrpx_worker.h"
82 #include "shrpx_http2_upstream.h"
83 #include "shrpx_http2_session.h"
84 #include "shrpx_worker_process.h"
85 #include "shrpx_process.h"
86 #include "shrpx_signal.h"
87 #include "shrpx_connection.h"
88 #include "shrpx_log.h"
90 #include "app_helper.h"
93 #include "allocator.h"
94 #include "ssl_compat.h"
95 #include "xsi_strerror.h"
97 extern char **environ;
99 using namespace nghttp2;
103 // Deprecated: Environment variables to tell new binary the listening
104 // socket's file descriptors. They are not close-on-exec.
105 constexpr auto ENV_LISTENER4_FD = StringRef::from_lit("NGHTTPX_LISTENER4_FD");
106 constexpr auto ENV_LISTENER6_FD = StringRef::from_lit("NGHTTPX_LISTENER6_FD");
108 // Deprecated: Environment variable to tell new binary the port number
109 // the current binary is listening to.
110 constexpr auto ENV_PORT = StringRef::from_lit("NGHTTPX_PORT");
112 // Deprecated: Environment variable to tell new binary the listening
113 // socket's file descriptor if frontend listens UNIX domain socket.
114 constexpr auto ENV_UNIX_FD = StringRef::from_lit("NGHTTP2_UNIX_FD");
115 // Deprecated: Environment variable to tell new binary the UNIX domain
117 constexpr auto ENV_UNIX_PATH = StringRef::from_lit("NGHTTP2_UNIX_PATH");
119 // Prefix of environment variables to tell new binary the listening
120 // socket's file descriptor. They are not close-on-exec. For TCP
121 // socket, the value must be comma separated 2 parameters: tcp,<FD>.
122 // <FD> is file descriptor. For UNIX domain socket, the value must be
123 // comma separated 3 parameters: unix,<FD>,<PATH>. <FD> is file
124 // descriptor. <PATH> is a path to UNIX domain socket.
125 constexpr auto ENV_ACCEPT_PREFIX = StringRef::from_lit("NGHTTPX_ACCEPT_");
127 // This environment variable contains PID of the original master
128 // process, assuming that it created this master process as a result
129 // of SIGUSR2. The new master process is expected to send QUIT signal
130 // to the original master process to shut it down gracefully.
131 constexpr auto ENV_ORIG_PID = StringRef::from_lit("NGHTTPX_ORIG_PID");
133 #ifndef _KERNEL_FASTOPEN
134 # define _KERNEL_FASTOPEN
135 // conditional define for TCP_FASTOPEN mostly on ubuntu
136 # ifndef TCP_FASTOPEN
137 # define TCP_FASTOPEN 23
140 // conditional define for SOL_TCP mostly on ubuntu
146 // This configuration is fixed at the first startup of the main
147 // process, and does not change after subsequent reloadings.
148 struct StartupConfig {
149 // This contains all options given in command-line.
150 std::vector<std::pair<StringRef, StringRef>> cmdcfgs;
151 // The current working directory where this process started.
153 // The pointer to original argv (not sure why we have this?)
154 char **original_argv;
155 // The pointer to argv, this is a deep copy of original argv.
157 // The number of elements in argv.
162 StartupConfig suconfig;
165 struct InheritedAddr {
166 // IP address if TCP socket. Otherwise, UNIX domain socket path.
169 // true if UNIX domain socket path
176 void signal_cb(struct ev_loop *loop, ev_signal *w, int revents);
180 void worker_process_child_cb(struct ev_loop *loop, ev_child *w, int revents);
183 struct WorkerProcess {
184 WorkerProcess(struct ev_loop *loop, pid_t worker_pid, int ipc_fd)
185 : loop(loop), worker_pid(worker_pid), ipc_fd(ipc_fd) {
186 ev_signal_init(&reopen_log_signalev, signal_cb, REOPEN_LOG_SIGNAL);
187 reopen_log_signalev.data = this;
188 ev_signal_start(loop, &reopen_log_signalev);
190 ev_signal_init(&exec_binary_signalev, signal_cb, EXEC_BINARY_SIGNAL);
191 exec_binary_signalev.data = this;
192 ev_signal_start(loop, &exec_binary_signalev);
194 ev_signal_init(&graceful_shutdown_signalev, signal_cb,
195 GRACEFUL_SHUTDOWN_SIGNAL);
196 graceful_shutdown_signalev.data = this;
197 ev_signal_start(loop, &graceful_shutdown_signalev);
199 ev_signal_init(&reload_signalev, signal_cb, RELOAD_SIGNAL);
200 reload_signalev.data = this;
201 ev_signal_start(loop, &reload_signalev);
203 ev_child_init(&worker_process_childev, worker_process_child_cb, worker_pid,
205 worker_process_childev.data = this;
206 ev_child_start(loop, &worker_process_childev);
210 shutdown_signal_watchers();
212 ev_child_stop(loop, &worker_process_childev);
215 shutdown(ipc_fd, SHUT_WR);
220 void shutdown_signal_watchers() {
221 ev_signal_stop(loop, &reopen_log_signalev);
222 ev_signal_stop(loop, &exec_binary_signalev);
223 ev_signal_stop(loop, &graceful_shutdown_signalev);
224 ev_signal_stop(loop, &reload_signalev);
227 ev_signal reopen_log_signalev;
228 ev_signal exec_binary_signalev;
229 ev_signal graceful_shutdown_signalev;
230 ev_signal reload_signalev;
231 ev_child worker_process_childev;
232 struct ev_loop *loop;
238 void reload_config(WorkerProcess *wp);
242 std::deque<std::unique_ptr<WorkerProcess>> worker_processes;
246 void worker_process_add(std::unique_ptr<WorkerProcess> wp) {
247 worker_processes.push_back(std::move(wp));
252 void worker_process_remove(const WorkerProcess *wp) {
253 for (auto it = std::begin(worker_processes); it != std::end(worker_processes);
261 worker_processes.erase(it);
268 void worker_process_remove_all() {
269 std::deque<std::unique_ptr<WorkerProcess>>().swap(worker_processes);
274 // Send signal |signum| to all worker processes, and clears
276 void worker_process_kill(int signum) {
277 for (auto &s : worker_processes) {
278 if (s->worker_pid == -1) {
281 kill(s->worker_pid, signum);
283 worker_process_remove_all();
288 // Returns the last PID of worker process. Returns -1 if there is no
289 // worker process at the moment.
290 int worker_process_last_pid() {
291 if (worker_processes.empty()) {
295 return worker_processes.back()->worker_pid;
301 std::array<char, STRERROR_BUFSIZE> errbuf;
302 auto config = get_config();
304 constexpr auto SUFFIX = StringRef::from_lit(".XXXXXX");
305 auto &pid_file = config->pid_file;
307 auto len = config->pid_file.size() + SUFFIX.size();
308 auto buf = std::make_unique<char[]>(len + 1);
311 p = std::copy(std::begin(pid_file), std::end(pid_file), p);
312 p = std::copy(std::begin(SUFFIX), std::end(SUFFIX), p);
315 auto temp_path = buf.get();
317 auto fd = mkstemp(temp_path);
320 LOG(ERROR) << "Could not save PID to file " << pid_file << ": "
321 << xsi_strerror(error, errbuf.data(), errbuf.size());
325 auto content = util::utos(config->pid) + '\n';
327 if (write(fd, content.c_str(), content.size()) == -1) {
329 LOG(ERROR) << "Could not save PID to file " << pid_file << ": "
330 << xsi_strerror(error, errbuf.data(), errbuf.size());
334 if (fsync(fd) == -1) {
336 LOG(ERROR) << "Could not save PID to file " << pid_file << ": "
337 << xsi_strerror(error, errbuf.data(), errbuf.size());
343 if (rename(temp_path, pid_file.c_str()) == -1) {
345 LOG(ERROR) << "Could not save PID to file " << pid_file << ": "
346 << xsi_strerror(error, errbuf.data(), errbuf.size());
353 if (config->uid != 0) {
354 if (chown(pid_file.c_str(), config->uid, config->gid) == -1) {
356 LOG(WARN) << "Changing owner of pid file " << pid_file << " failed: "
357 << xsi_strerror(error, errbuf.data(), errbuf.size());
366 void shrpx_sd_notifyf(int unset_environment, const char *format, ...) {
367 #ifdef HAVE_LIBSYSTEMD
370 va_start(args, format);
371 sd_notifyf(unset_environment, format, va_arg(args, char *));
373 #endif // HAVE_LIBSYSTEMD
381 std::array<char, STRERROR_BUFSIZE> errbuf;
383 LOG(NOTICE) << "Executing new binary";
385 shrpx_sd_notifyf(0, "RELOADING=1");
387 rv = shrpx_signal_block_all(&oldset);
390 LOG(ERROR) << "Blocking all signals failed: "
391 << xsi_strerror(error, errbuf.data(), errbuf.size());
401 LOG(ERROR) << "fork() failed errno=" << error;
403 // update PID tracking information in systemd
404 shrpx_sd_notifyf(0, "MAINPID=%d\n", pid);
407 rv = shrpx_signal_set(&oldset);
411 LOG(FATAL) << "Restoring signal mask failed: "
412 << xsi_strerror(error, errbuf.data(), errbuf.size());
422 shrpx_signal_unset_master_proc_ign_handler();
424 rv = shrpx_signal_unblock_all();
427 LOG(ERROR) << "Unblocking all signals failed: "
428 << xsi_strerror(error, errbuf.data(), errbuf.size());
430 nghttp2_Exit(EXIT_FAILURE);
434 util::get_exec_path(suconfig.argc, suconfig.argv, suconfig.cwd);
437 LOG(ERROR) << "Could not resolve the executable path";
438 nghttp2_Exit(EXIT_FAILURE);
441 auto argv = std::make_unique<char *[]>(suconfig.argc + 1);
444 for (int i = 1; i < suconfig.argc; ++i) {
445 argv[i] = suconfig.argv[i];
447 argv[suconfig.argc] = nullptr;
450 for (char **p = environ; *p; ++p, ++envlen)
453 auto config = get_config();
454 auto &listenerconf = config->conn.listener;
456 // 2 for ENV_ORIG_PID and terminal nullptr.
458 std::make_unique<char *[]>(envlen + listenerconf.addrs.size() + 2);
461 std::vector<ImmutableString> fd_envs;
462 for (size_t i = 0; i < listenerconf.addrs.size(); ++i) {
463 auto &addr = listenerconf.addrs[i];
464 auto s = ENV_ACCEPT_PREFIX.str();
465 s += util::utos(i + 1);
467 if (addr.host_unix) {
469 s += util::utos(addr.fd);
474 s += util::utos(addr.fd);
477 fd_envs.emplace_back(s);
478 envp[envidx++] = const_cast<char *>(fd_envs.back().c_str());
481 auto ipc_fd_str = ENV_ORIG_PID.str();
483 ipc_fd_str += util::utos(config->pid);
484 envp[envidx++] = const_cast<char *>(ipc_fd_str.c_str());
486 for (size_t i = 0; i < envlen; ++i) {
487 auto env = StringRef{environ[i]};
488 if (util::starts_with(env, ENV_ACCEPT_PREFIX) ||
489 util::starts_with(env, ENV_LISTENER4_FD) ||
490 util::starts_with(env, ENV_LISTENER6_FD) ||
491 util::starts_with(env, ENV_PORT) ||
492 util::starts_with(env, ENV_UNIX_FD) ||
493 util::starts_with(env, ENV_UNIX_PATH) ||
494 util::starts_with(env, ENV_ORIG_PID)) {
498 envp[envidx++] = environ[i];
501 envp[envidx++] = nullptr;
503 if (LOG_ENABLED(INFO)) {
504 LOG(INFO) << "cmdline";
505 for (int i = 0; argv[i]; ++i) {
506 LOG(INFO) << i << ": " << argv[i];
508 LOG(INFO) << "environ";
509 for (int i = 0; envp[i]; ++i) {
510 LOG(INFO) << i << ": " << envp[i];
514 // restores original stderr
515 restore_original_fds();
517 // reloading finished
518 shrpx_sd_notifyf(0, "READY=1");
520 if (execve(argv[0], argv.get(), envp.get()) == -1) {
522 LOG(ERROR) << "execve failed: errno=" << error;
523 nghttp2_Exit(EXIT_FAILURE);
529 void ipc_send(WorkerProcess *wp, uint8_t ipc_event) {
530 std::array<char, STRERROR_BUFSIZE> errbuf;
532 while ((nwrite = write(wp->ipc_fd, &ipc_event, 1)) == -1 && errno == EINTR)
537 LOG(ERROR) << "Could not send IPC event to worker process: "
538 << xsi_strerror(error, errbuf.data(), errbuf.size());
543 LOG(ERROR) << "Could not send IPC event due to pipe overflow";
550 void reopen_log(WorkerProcess *wp) {
551 LOG(NOTICE) << "Reopening log files: master process";
553 auto config = get_config();
554 auto &loggingconf = config->logging;
556 (void)reopen_log_files(loggingconf);
557 redirect_stderr_to_errorlog(loggingconf);
558 ipc_send(wp, SHRPX_IPC_REOPEN_LOG);
563 void signal_cb(struct ev_loop *loop, ev_signal *w, int revents) {
564 auto wp = static_cast<WorkerProcess *>(w->data);
565 if (wp->worker_pid == -1) {
571 case REOPEN_LOG_SIGNAL:
574 case EXEC_BINARY_SIGNAL:
577 case GRACEFUL_SHUTDOWN_SIGNAL: {
578 auto &listenerconf = get_config()->conn.listener;
579 for (auto &addr : listenerconf.addrs) {
582 ipc_send(wp, SHRPX_IPC_GRACEFUL_SHUTDOWN);
589 worker_process_kill(w->signum);
597 void worker_process_child_cb(struct ev_loop *loop, ev_child *w, int revents) {
598 auto wp = static_cast<WorkerProcess *>(w->data);
600 log_chld(w->rpid, w->rstatus, "Worker process");
602 auto pid = wp->worker_pid;
604 worker_process_remove(wp);
606 if (worker_process_last_pid() == pid) {
613 int create_unix_domain_server_socket(UpstreamAddr &faddr,
614 std::vector<InheritedAddr> &iaddrs) {
615 std::array<char, STRERROR_BUFSIZE> errbuf;
616 auto found = std::find_if(
617 std::begin(iaddrs), std::end(iaddrs), [&faddr](const InheritedAddr &ia) {
618 return !ia.used && ia.host_unix && ia.host == faddr.host;
621 if (found != std::end(iaddrs)) {
622 LOG(NOTICE) << "Listening on UNIX domain socket " << faddr.host
623 << (faddr.tls ? ", tls" : "");
624 (*found).used = true;
625 faddr.fd = (*found).fd;
626 faddr.hostport = StringRef::from_lit("localhost");
632 auto fd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0);
635 LOG(FATAL) << "socket() syscall failed: "
636 << xsi_strerror(error, errbuf.data(), errbuf.size());
639 #else // !SOCK_NONBLOCK
640 auto fd = socket(AF_UNIX, SOCK_STREAM, 0);
643 LOG(FATAL) << "socket() syscall failed: "
644 << xsi_strerror(error, errbuf.data(), errbuf.size());
647 util::make_socket_nonblocking(fd);
648 #endif // !SOCK_NONBLOCK
650 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val,
651 static_cast<socklen_t>(sizeof(val))) == -1) {
653 LOG(FATAL) << "Failed to set SO_REUSEADDR option to listener socket: "
654 << xsi_strerror(error, errbuf.data(), errbuf.size());
660 addr.un.sun_family = AF_UNIX;
661 if (faddr.host.size() + 1 > sizeof(addr.un.sun_path)) {
662 LOG(FATAL) << "UNIX domain socket path " << faddr.host << " is too long > "
663 << sizeof(addr.un.sun_path);
667 // copy path including terminal NULL
668 std::copy_n(faddr.host.c_str(), faddr.host.size() + 1, addr.un.sun_path);
670 // unlink (remove) already existing UNIX domain socket path
671 unlink(faddr.host.c_str());
673 if (bind(fd, &addr.sa, sizeof(addr.un)) != 0) {
675 LOG(FATAL) << "Failed to bind UNIX domain socket: "
676 << xsi_strerror(error, errbuf.data(), errbuf.size());
681 auto &listenerconf = get_config()->conn.listener;
683 if (listen(fd, listenerconf.backlog) != 0) {
685 LOG(FATAL) << "Failed to listen to UNIX domain socket: "
686 << xsi_strerror(error, errbuf.data(), errbuf.size());
691 LOG(NOTICE) << "Listening on UNIX domain socket " << faddr.host
692 << (faddr.tls ? ", tls" : "");
695 faddr.hostport = StringRef::from_lit("localhost");
702 int create_tcp_server_socket(UpstreamAddr &faddr,
703 std::vector<InheritedAddr> &iaddrs) {
704 std::array<char, STRERROR_BUFSIZE> errbuf;
708 auto &listenerconf = get_config()->conn.listener;
710 auto service = util::utos(faddr.port);
712 hints.ai_family = faddr.family;
713 hints.ai_socktype = SOCK_STREAM;
714 hints.ai_flags = AI_PASSIVE;
716 hints.ai_flags |= AI_ADDRCONFIG;
717 #endif // AI_ADDRCONFIG
720 faddr.host == StringRef::from_lit("*") ? nullptr : faddr.host.c_str();
723 rv = getaddrinfo(node, service.c_str(), &hints, &res);
726 // Retry without AI_ADDRCONFIG
727 hints.ai_flags &= ~AI_ADDRCONFIG;
728 rv = getaddrinfo(node, service.c_str(), &hints, &res);
730 #endif // AI_ADDRCONFIG
732 LOG(FATAL) << "Unable to get IPv" << (faddr.family == AF_INET ? "4" : "6")
733 << " address for " << faddr.host << ", port " << faddr.port
734 << ": " << gai_strerror(rv);
738 auto res_d = defer(freeaddrinfo, res);
740 std::array<char, NI_MAXHOST> host;
742 for (rp = res; rp; rp = rp->ai_next) {
744 rv = getnameinfo(rp->ai_addr, rp->ai_addrlen, host.data(), host.size(),
745 nullptr, 0, NI_NUMERICHOST);
748 LOG(WARN) << "getnameinfo() failed: " << gai_strerror(rv);
752 auto found = std::find_if(std::begin(iaddrs), std::end(iaddrs),
753 [&host, &faddr](const InheritedAddr &ia) {
754 return !ia.used && !ia.host_unix &&
755 ia.host == host.data() &&
756 ia.port == faddr.port;
759 if (found != std::end(iaddrs)) {
760 (*found).used = true;
767 socket(rp->ai_family, rp->ai_socktype | SOCK_NONBLOCK, rp->ai_protocol);
770 LOG(WARN) << "socket() syscall failed: "
771 << xsi_strerror(error, errbuf.data(), errbuf.size());
774 #else // !SOCK_NONBLOCK
775 fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
778 LOG(WARN) << "socket() syscall failed: "
779 << xsi_strerror(error, errbuf.data(), errbuf.size());
782 util::make_socket_nonblocking(fd);
783 #endif // !SOCK_NONBLOCK
785 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val,
786 static_cast<socklen_t>(sizeof(val))) == -1) {
788 LOG(WARN) << "Failed to set SO_REUSEADDR option to listener socket: "
789 << xsi_strerror(error, errbuf.data(), errbuf.size());
795 if (faddr.family == AF_INET6) {
796 if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &val,
797 static_cast<socklen_t>(sizeof(val))) == -1) {
799 LOG(WARN) << "Failed to set IPV6_V6ONLY option to listener socket: "
800 << xsi_strerror(error, errbuf.data(), errbuf.size());
805 #endif // IPV6_V6ONLY
807 #ifdef TCP_DEFER_ACCEPT
809 if (setsockopt(fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &val,
810 static_cast<socklen_t>(sizeof(val))) == -1) {
812 LOG(WARN) << "Failed to set TCP_DEFER_ACCEPT option to listener socket: "
813 << xsi_strerror(error, errbuf.data(), errbuf.size());
815 #endif // TCP_DEFER_ACCEPT
817 // When we are executing new binary, and the old binary did not
818 // bind privileged port (< 1024) for some reason, binding to those
819 // ports will fail with permission denied error.
820 if (bind(fd, rp->ai_addr, rp->ai_addrlen) == -1) {
822 LOG(WARN) << "bind() syscall failed: "
823 << xsi_strerror(error, errbuf.data(), errbuf.size());
828 if (listenerconf.fastopen > 0) {
829 val = listenerconf.fastopen;
830 if (setsockopt(fd, SOL_TCP, TCP_FASTOPEN, &val,
831 static_cast<socklen_t>(sizeof(val))) == -1) {
833 LOG(WARN) << "Failed to set TCP_FASTOPEN option to listener socket: "
834 << xsi_strerror(error, errbuf.data(), errbuf.size());
838 if (listen(fd, listenerconf.backlog) == -1) {
840 LOG(WARN) << "listen() syscall failed: "
841 << xsi_strerror(error, errbuf.data(), errbuf.size());
850 LOG(FATAL) << "Listening " << (faddr.family == AF_INET ? "IPv4" : "IPv6")
857 faddr.hostport = util::make_http_hostport(mod_config()->balloc,
858 StringRef{host.data()}, faddr.port);
860 LOG(NOTICE) << "Listening on " << faddr.hostport
861 << (faddr.tls ? ", tls" : "");
868 // Returns array of InheritedAddr constructed from |config|. This
869 // function is intended to be used when reloading configuration, and
870 // |config| is usually a current configuration.
871 std::vector<InheritedAddr>
872 get_inherited_addr_from_config(BlockAllocator &balloc, Config *config) {
873 std::array<char, STRERROR_BUFSIZE> errbuf;
876 auto &listenerconf = config->conn.listener;
878 std::vector<InheritedAddr> iaddrs(listenerconf.addrs.size());
881 for (auto &addr : listenerconf.addrs) {
882 auto &iaddr = iaddrs[idx++];
884 if (addr.host_unix) {
885 iaddr.host = addr.host;
886 iaddr.host_unix = true;
892 iaddr.port = addr.port;
895 // We have to getsockname/getnameinfo for fd, since we may have
896 // '*' appear in addr.host, which makes comparison against "real"
900 socklen_t salen = sizeof(su);
902 // We already added entry to iaddrs. Even if we got errors, we
903 // don't remove it. This is required because we have to close the
904 // socket if it is not reused. The empty host name usually does
905 // not match anything.
907 if (getsockname(addr.fd, &su.sa, &salen) != 0) {
909 LOG(WARN) << "getsockname() syscall failed (fd=" << addr.fd
910 << "): " << xsi_strerror(error, errbuf.data(), errbuf.size());
914 std::array<char, NI_MAXHOST> host;
915 rv = getnameinfo(&su.sa, salen, host.data(), host.size(), nullptr, 0,
918 LOG(WARN) << "getnameinfo() failed (fd=" << addr.fd
919 << "): " << gai_strerror(rv);
923 iaddr.host = make_string_ref(balloc, StringRef{host.data()});
931 // Returns array of InheritedAddr constructed from environment
932 // variables. This function handles the old environment variable
933 // names used in 1.7.0 or earlier.
934 std::vector<InheritedAddr> get_inherited_addr_from_env(Config *config) {
935 std::array<char, STRERROR_BUFSIZE> errbuf;
937 std::vector<InheritedAddr> iaddrs;
940 // Upgrade from 1.7.0 or earlier
941 auto portenv = getenv(ENV_PORT.c_str());
944 for (auto env_name : {ENV_LISTENER4_FD, ENV_LISTENER6_FD}) {
945 auto fdenv = getenv(env_name.c_str());
947 auto name = ENV_ACCEPT_PREFIX.str();
948 name += util::utos(i);
949 std::string value = "tcp,";
951 setenv(name.c_str(), value.c_str(), 0);
956 // The return value of getenv may be allocated statically.
957 if (getenv(ENV_UNIX_PATH.c_str()) && getenv(ENV_UNIX_FD.c_str())) {
958 auto name = ENV_ACCEPT_PREFIX.str();
960 std::string value = "unix,";
961 value += getenv(ENV_UNIX_FD.c_str());
963 value += getenv(ENV_UNIX_PATH.c_str());
964 setenv(name.c_str(), value.c_str(), 0);
969 for (size_t i = 1;; ++i) {
970 auto name = ENV_ACCEPT_PREFIX.str();
971 name += util::utos(i);
972 auto env = getenv(name.c_str());
977 if (LOG_ENABLED(INFO)) {
978 LOG(INFO) << "Read env " << name << "=" << env;
981 auto end_type = strchr(env, ',');
986 auto type = StringRef(env, end_type);
987 auto value = end_type + 1;
989 if (type == StringRef::from_lit("unix")) {
990 auto endfd = strchr(value, ',');
994 auto fd = util::parse_uint(reinterpret_cast<const uint8_t *>(value),
997 LOG(WARN) << "Could not parse file descriptor from "
998 << std::string(value, endfd - value);
1002 auto path = endfd + 1;
1003 if (strlen(path) == 0) {
1004 LOG(WARN) << "Empty UNIX domain socket path (fd=" << fd << ")";
1009 if (LOG_ENABLED(INFO)) {
1010 LOG(INFO) << "Inherit UNIX domain socket fd=" << fd
1011 << ", path=" << path;
1014 InheritedAddr addr{};
1015 addr.host = make_string_ref(config->balloc, StringRef{path});
1016 addr.host_unix = true;
1017 addr.fd = static_cast<int>(fd);
1018 iaddrs.push_back(std::move(addr));
1021 if (type == StringRef::from_lit("tcp")) {
1022 auto fd = util::parse_uint(value);
1024 LOG(WARN) << "Could not parse file descriptor from " << value;
1029 socklen_t salen = sizeof(su);
1031 if (getsockname(fd, &su.sa, &salen) != 0) {
1033 LOG(WARN) << "getsockname() syscall failed (fd=" << fd
1034 << "): " << xsi_strerror(error, errbuf.data(), errbuf.size());
1041 switch (su.storage.ss_family) {
1043 port = ntohs(su.in.sin_port);
1046 port = ntohs(su.in6.sin6_port);
1053 std::array<char, NI_MAXHOST> host;
1054 rv = getnameinfo(&su.sa, salen, host.data(), host.size(), nullptr, 0,
1057 LOG(WARN) << "getnameinfo() failed (fd=" << fd
1058 << "): " << gai_strerror(rv);
1063 if (LOG_ENABLED(INFO)) {
1064 LOG(INFO) << "Inherit TCP socket fd=" << fd
1065 << ", address=" << host.data() << ", port=" << port;
1068 InheritedAddr addr{};
1069 addr.host = make_string_ref(config->balloc, StringRef{host.data()});
1070 addr.port = static_cast<uint16_t>(port);
1071 addr.fd = static_cast<int>(fd);
1072 iaddrs.push_back(std::move(addr));
1082 // Closes all sockets which are not reused.
1083 void close_unused_inherited_addr(const std::vector<InheritedAddr> &iaddrs) {
1084 for (auto &ia : iaddrs) {
1095 // Returns the PID of the original master process from environment
1096 // variable ENV_ORIG_PID.
1097 pid_t get_orig_pid_from_env() {
1098 auto s = getenv(ENV_ORIG_PID.c_str());
1102 return util::parse_uint(s);
1107 int create_acceptor_socket(Config *config, std::vector<InheritedAddr> &iaddrs) {
1108 std::array<char, STRERROR_BUFSIZE> errbuf;
1109 auto &listenerconf = config->conn.listener;
1111 for (auto &addr : listenerconf.addrs) {
1112 if (addr.host_unix) {
1113 if (create_unix_domain_server_socket(addr, iaddrs) != 0) {
1117 if (config->uid != 0) {
1118 // fd is not associated to inode, so we cannot use fchown(2)
1119 // here. https://lkml.org/lkml/2004/11/1/84
1120 if (chown(addr.host.c_str(), config->uid, config->gid) == -1) {
1122 LOG(WARN) << "Changing owner of UNIX domain socket " << addr.host
1124 << xsi_strerror(error, errbuf.data(), errbuf.size());
1130 if (create_tcp_server_socket(addr, iaddrs) != 0) {
1142 return _daemonize(0, 0, 0, 0);
1144 # ifdef HAVE_LIBSYSTEMD
1145 if (sd_booted() && (getenv("NOTIFY_SOCKET") != nullptr)) {
1146 LOG(NOTICE) << "Daemonising disabled under systemd";
1150 # endif // HAVE_LIBSYSTEMD
1151 return util::daemonize(0, 0);
1157 // Opens IPC socket used to communicate with worker proess. The
1158 // communication is unidirectional; that is main process sends
1159 // messages to the worker process. On success, ipc_fd[0] is for
1160 // reading, and ipc_fd[1] for writing, just like pipe(2).
1161 int create_ipc_socket(std::array<int, 2> &ipc_fd) {
1162 std::array<char, STRERROR_BUFSIZE> errbuf;
1165 rv = pipe(ipc_fd.data());
1168 LOG(WARN) << "Failed to create pipe to communicate worker process: "
1169 << xsi_strerror(error, errbuf.data(), errbuf.size());
1173 for (int i = 0; i < 2; ++i) {
1174 auto fd = ipc_fd[i];
1175 util::make_socket_nonblocking(fd);
1176 util::make_socket_closeonexec(fd);
1184 // Creates worker process, and returns PID of worker process. On
1185 // success, file descriptor for IPC (send only) is assigned to
1186 // |main_ipc_fd|. In child process, we will close file descriptors
1187 // which are inherited from previous configuration/process, but not
1188 // used in the current configuration.
1189 pid_t fork_worker_process(int &main_ipc_fd,
1190 const std::vector<InheritedAddr> &iaddrs) {
1191 std::array<char, STRERROR_BUFSIZE> errbuf;
1195 std::array<int, 2> ipc_fd;
1197 rv = create_ipc_socket(ipc_fd);
1202 rv = shrpx_signal_block_all(&oldset);
1205 LOG(ERROR) << "Blocking all signals failed: "
1206 << xsi_strerror(error, errbuf.data(), errbuf.size());
1214 auto config = get_config();
1218 if (!config->single_process) {
1223 ev_loop_fork(EV_DEFAULT);
1225 for (auto &addr : config->conn.listener.addrs) {
1226 util::make_socket_closeonexec(addr.fd);
1229 // Remove all WorkerProcesses to stop any registered watcher on
1231 worker_process_remove_all();
1233 close_unused_inherited_addr(iaddrs);
1235 shrpx_signal_set_worker_proc_ign_handler();
1237 rv = shrpx_signal_unblock_all();
1240 LOG(FATAL) << "Unblocking all signals failed: "
1241 << xsi_strerror(error, errbuf.data(), errbuf.size());
1243 if (config->single_process) {
1246 nghttp2_Exit(EXIT_FAILURE);
1250 if (!config->single_process) {
1254 WorkerProcessConfig wpconf{ipc_fd[0]};
1255 rv = worker_process_event_loop(&wpconf);
1257 LOG(FATAL) << "Worker process returned error";
1259 if (config->single_process) {
1262 nghttp2_Exit(EXIT_FAILURE);
1266 LOG(NOTICE) << "Worker process shutting down momentarily";
1268 // call exit(...) instead of nghttp2_Exit to get leak sanitizer report
1269 if (config->single_process) {
1272 nghttp2_Exit(EXIT_SUCCESS);
1279 LOG(ERROR) << "Could not spawn worker process: "
1280 << xsi_strerror(error, errbuf.data(), errbuf.size());
1283 rv = shrpx_signal_set(&oldset);
1286 LOG(FATAL) << "Restoring signal mask failed: "
1287 << xsi_strerror(error, errbuf.data(), errbuf.size());
1301 main_ipc_fd = ipc_fd[1];
1303 LOG(NOTICE) << "Worker process [" << pid << "] spawned";
1311 std::array<char, STRERROR_BUFSIZE> errbuf;
1313 shrpx_signal_set_master_proc_ign_handler();
1315 auto config = mod_config();
1317 if (config->daemon) {
1318 if (call_daemon() == -1) {
1320 LOG(FATAL) << "Failed to daemonize: "
1321 << xsi_strerror(error, errbuf.data(), errbuf.size());
1325 // We get new PID after successful daemon().
1326 mod_config()->pid = getpid();
1328 // daemon redirects stderr file descriptor to /dev/null, so we
1330 redirect_stderr_to_errorlog(config->logging);
1333 // update systemd PID tracking
1334 shrpx_sd_notifyf(0, "MAINPID=%d\n", config->pid);
1337 auto iaddrs = get_inherited_addr_from_env(config);
1339 if (create_acceptor_socket(config, iaddrs) != 0) {
1343 close_unused_inherited_addr(iaddrs);
1346 auto orig_pid = get_orig_pid_from_env();
1348 auto loop = ev_default_loop(config->ev_loop_flags);
1352 auto pid = fork_worker_process(ipc_fd, {});
1358 worker_process_add(std::make_unique<WorkerProcess>(loop, pid, ipc_fd));
1360 // Write PID file when we are ready to accept connection from peer.
1361 // This makes easier to write restart script for nghttpx. Because
1362 // when we know that PID file is recreated, it means we can send
1363 // QUIT signal to the old process to make it shutdown gracefully.
1364 if (!config->pid_file.empty()) {
1368 // ready to serve requests
1369 shrpx_sd_notifyf(0, "READY=1");
1371 if (orig_pid != -1) {
1372 LOG(NOTICE) << "Send QUIT signal to the original master process to tell "
1373 "that we are ready to serve requests.";
1374 kill(orig_pid, SIGQUIT);
1384 // Returns true if regular file or symbolic link |path| exists.
1385 bool conf_exists(const char *path) {
1387 int rv = stat(path, &buf);
1388 return rv == 0 && (buf.st_mode & (S_IFREG | S_IFLNK));
1393 constexpr auto DEFAULT_NPN_LIST =
1394 StringRef::from_lit("h2,h2-16,h2-14,http/1.1");
1398 constexpr auto DEFAULT_TLS_MIN_PROTO_VERSION = StringRef::from_lit("TLSv1.2");
1399 #ifdef TLS1_3_VERSION
1400 constexpr auto DEFAULT_TLS_MAX_PROTO_VERSION = StringRef::from_lit("TLSv1.3");
1401 #else // !TLS1_3_VERSION
1402 constexpr auto DEFAULT_TLS_MAX_PROTO_VERSION = StringRef::from_lit("TLSv1.2");
1403 #endif // !TLS1_3_VERSION
1407 constexpr auto DEFAULT_ACCESSLOG_FORMAT =
1408 StringRef::from_lit(R"($remote_addr - - [$time_local] )"
1409 R"("$request" $status $body_bytes_sent )"
1410 R"("$http_referer" "$http_user_agent")");
1414 void fill_default_config(Config *config) {
1415 config->num_worker = 1;
1416 config->conf_path = StringRef::from_lit("/etc/nghttpx/nghttpx.conf");
1417 config->pid = getpid();
1420 config->single_thread = true;
1423 if (ev_supported_backends() & ~ev_recommended_backends() & EVBACKEND_KQUEUE) {
1424 config->ev_loop_flags = ev_recommended_backends() | EVBACKEND_KQUEUE;
1427 auto &tlsconf = config->tls;
1429 auto &ticketconf = tlsconf.ticket;
1431 auto &memcachedconf = ticketconf.memcached;
1432 memcachedconf.max_retry = 3;
1433 memcachedconf.max_fail = 2;
1434 memcachedconf.interval = 10_min;
1435 memcachedconf.family = AF_UNSPEC;
1438 auto &session_cacheconf = tlsconf.session_cache;
1440 auto &memcachedconf = session_cacheconf.memcached;
1441 memcachedconf.family = AF_UNSPEC;
1444 ticketconf.cipher = EVP_aes_128_cbc();
1448 auto &ocspconf = tlsconf.ocsp;
1449 // ocsp update interval = 14400 secs = 4 hours, borrowed from h2o
1450 ocspconf.update_interval = 4_h;
1451 ocspconf.fetch_ocsp_response_file =
1452 StringRef::from_lit(PKGDATADIR "/fetch-ocsp-response");
1456 auto &dyn_recconf = tlsconf.dyn_rec;
1457 dyn_recconf.warmup_threshold = 1_m;
1458 dyn_recconf.idle_timeout = 1_s;
1461 tlsconf.session_timeout = std::chrono::hours(12);
1462 tlsconf.ciphers = StringRef::from_lit(nghttp2::tls::DEFAULT_CIPHER_LIST);
1463 tlsconf.tls13_ciphers =
1464 StringRef::from_lit(nghttp2::tls::DEFAULT_TLS13_CIPHER_LIST);
1465 tlsconf.client.ciphers =
1466 StringRef::from_lit(nghttp2::tls::DEFAULT_CIPHER_LIST);
1467 tlsconf.client.tls13_ciphers =
1468 StringRef::from_lit(nghttp2::tls::DEFAULT_TLS13_CIPHER_LIST);
1469 tlsconf.min_proto_version =
1470 tls::proto_version_from_string(DEFAULT_TLS_MIN_PROTO_VERSION);
1471 tlsconf.max_proto_version =
1472 tls::proto_version_from_string(DEFAULT_TLS_MAX_PROTO_VERSION);
1473 tlsconf.max_early_data = 16_k;
1474 #if OPENSSL_1_1_API || defined(OPENSSL_IS_BORINGSSL)
1475 tlsconf.ecdh_curves = StringRef::from_lit("X25519:P-256:P-384:P-521");
1476 #else // !OPENSSL_1_1_API && !defined(OPENSSL_IS_BORINGSSL)
1477 tlsconf.ecdh_curves = StringRef::from_lit("P-256:P-384:P-521");
1478 #endif // !OPENSSL_1_1_API && !defined(OPENSSL_IS_BORINGSSL)
1480 auto &httpconf = config->http;
1481 httpconf.server_name = StringRef::from_lit("nghttpx");
1482 httpconf.no_host_rewrite = true;
1483 httpconf.request_header_field_buffer = 64_k;
1484 httpconf.max_request_header_fields = 100;
1485 httpconf.response_header_field_buffer = 64_k;
1486 httpconf.max_response_header_fields = 500;
1487 httpconf.redirect_https_port = StringRef::from_lit("443");
1488 httpconf.max_requests = std::numeric_limits<size_t>::max();
1489 httpconf.xfp.add = true;
1490 httpconf.xfp.strip_incoming = true;
1491 httpconf.early_data.strip_incoming = true;
1493 auto &http2conf = config->http2;
1495 auto &upstreamconf = http2conf.upstream;
1498 auto &timeoutconf = upstreamconf.timeout;
1499 timeoutconf.settings = 10_s;
1502 // window size for HTTP/2 upstream connection per stream. 2**16-1
1503 // = 64KiB-1, which is HTTP/2 default.
1504 upstreamconf.window_size = 64_k - 1;
1505 // HTTP/2 has connection-level flow control. The default window
1506 // size for HTTP/2 is 64KiB - 1.
1507 upstreamconf.connection_window_size = 64_k - 1;
1508 upstreamconf.max_concurrent_streams = 100;
1510 upstreamconf.encoder_dynamic_table_size = 4_k;
1511 upstreamconf.decoder_dynamic_table_size = 4_k;
1513 nghttp2_option_new(&upstreamconf.option);
1514 nghttp2_option_set_no_auto_window_update(upstreamconf.option, 1);
1515 nghttp2_option_set_no_recv_client_magic(upstreamconf.option, 1);
1516 nghttp2_option_set_max_deflate_dynamic_table_size(
1517 upstreamconf.option, upstreamconf.encoder_dynamic_table_size);
1519 // For API endpoint, we enable automatic window update. This is
1520 // because we are a sink.
1521 nghttp2_option_new(&upstreamconf.alt_mode_option);
1522 nghttp2_option_set_no_recv_client_magic(upstreamconf.alt_mode_option, 1);
1523 nghttp2_option_set_max_deflate_dynamic_table_size(
1524 upstreamconf.alt_mode_option, upstreamconf.encoder_dynamic_table_size);
1527 http2conf.timeout.stream_write = 1_min;
1530 auto &downstreamconf = http2conf.downstream;
1533 auto &timeoutconf = downstreamconf.timeout;
1534 timeoutconf.settings = 10_s;
1537 downstreamconf.window_size = 64_k - 1;
1538 downstreamconf.connection_window_size = (1u << 31) - 1;
1539 downstreamconf.max_concurrent_streams = 100;
1541 downstreamconf.encoder_dynamic_table_size = 4_k;
1542 downstreamconf.decoder_dynamic_table_size = 4_k;
1544 nghttp2_option_new(&downstreamconf.option);
1545 nghttp2_option_set_no_auto_window_update(downstreamconf.option, 1);
1546 nghttp2_option_set_peer_max_concurrent_streams(downstreamconf.option, 100);
1547 nghttp2_option_set_max_deflate_dynamic_table_size(
1548 downstreamconf.option, downstreamconf.encoder_dynamic_table_size);
1551 auto &loggingconf = config->logging;
1553 auto &accessconf = loggingconf.access;
1555 parse_log_format(config->balloc, DEFAULT_ACCESSLOG_FORMAT);
1557 auto &errorconf = loggingconf.error;
1558 errorconf.file = StringRef::from_lit("/dev/stderr");
1561 loggingconf.syslog_facility = LOG_DAEMON;
1562 loggingconf.severity = NOTICE;
1564 auto &connconf = config->conn;
1566 auto &listenerconf = connconf.listener;
1568 // Default accept() backlog
1569 listenerconf.backlog = 65536;
1570 listenerconf.timeout.sleep = 30_s;
1575 auto &upstreamconf = connconf.upstream;
1577 auto &timeoutconf = upstreamconf.timeout;
1578 // Read timeout for HTTP2 upstream connection
1579 timeoutconf.http2_read = 3_min;
1581 // Read timeout for non-HTTP2 upstream connection
1582 timeoutconf.read = 1_min;
1584 // Write timeout for HTTP2/non-HTTP2 upstream connection
1585 timeoutconf.write = 30_s;
1587 // Keep alive timeout for HTTP/1 upstream connection
1588 timeoutconf.idle_read = 1_min;
1593 connconf.downstream = std::make_shared<DownstreamConfig>();
1594 auto &downstreamconf = *connconf.downstream;
1596 auto &timeoutconf = downstreamconf.timeout;
1597 // Read/Write timeouts for downstream connection
1598 timeoutconf.read = 1_min;
1599 timeoutconf.write = 30_s;
1600 // Timeout for pooled (idle) connections
1601 timeoutconf.idle_read = 2_s;
1602 timeoutconf.connect = 30_s;
1603 timeoutconf.max_backoff = 120_s;
1606 downstreamconf.connections_per_host = 8;
1607 downstreamconf.request_buffer_size = 16_k;
1608 downstreamconf.response_buffer_size = 128_k;
1609 downstreamconf.family = AF_UNSPEC;
1612 auto &apiconf = config->api;
1613 apiconf.max_request_body = 32_m;
1615 auto &dnsconf = config->dns;
1617 auto &timeoutconf = dnsconf.timeout;
1618 timeoutconf.cache = 10_s;
1619 timeoutconf.lookup = 5_s;
1621 dnsconf.max_try = 2;
1627 void print_version(std::ostream &out) {
1628 out << "nghttpx nghttp2/" NGHTTP2_VERSION << std::endl;
1633 void print_usage(std::ostream &out) {
1634 out << R"(Usage: nghttpx [OPTIONS]... [<PRIVATE_KEY> <CERT>]
1635 A reverse proxy for HTTP/2, and HTTP/1.)"
1641 void print_help(std::ostream &out) {
1642 auto config = get_config();
1647 Set path to server's private key. Required unless
1648 "no-tls" parameter is used in --frontend option.
1649 <CERT> Set path to server's certificate. Required unless
1650 "no-tls" parameter is used in --frontend option. To
1651 make OCSP stapling work, this must be an absolute path.
1654 The options are categorized into several groups.
1657 -b, --backend=(<HOST>,<PORT>|unix:<PATH>)[;[<PATTERN>[:...]][[;<PARAM>]...]
1659 Set backend host and port. The multiple backend
1660 addresses are accepted by repeating this option. UNIX
1661 domain socket can be specified by prefixing path name
1662 with "unix:" (e.g., unix:/var/run/backend.sock).
1664 Optionally, if <PATTERN>s are given, the backend address
1665 is only used if request matches the pattern. The
1666 pattern matching is closely designed to ServeMux in
1667 net/http package of Go programming language. <PATTERN>
1668 consists of path, host + path or just host. The path
1669 must start with "/". If it ends with "/", it matches
1670 all request path in its subtree. To deal with the
1671 request to the directory without trailing slash, the
1672 path which ends with "/" also matches the request path
1673 which only lacks trailing '/' (e.g., path "/foo/"
1674 matches request path "/foo"). If it does not end with
1675 "/", it performs exact match against the request path.
1676 If host is given, it performs a match against the
1677 request host. For a request received on the frontend
1678 listener with "sni-fwd" parameter enabled, SNI host is
1679 used instead of a request host. If host alone is given,
1680 "/" is appended to it, so that it matches all request
1681 paths under the host (e.g., specifying "nghttp2.org"
1682 equals to "nghttp2.org/"). CONNECT method is treated
1683 specially. It does not have path, and we don't allow
1684 empty path. To workaround this, we assume that CONNECT
1685 method has "/" as path.
1687 Patterns with host take precedence over patterns with
1688 just path. Then, longer patterns take precedence over
1691 Host can include "*" in the left most position to
1692 indicate wildcard match (only suffix match is done).
1693 The "*" must match at least one character. For example,
1694 host pattern "*.nghttp2.org" matches against
1695 "www.nghttp2.org" and "git.ngttp2.org", but does not
1696 match against "nghttp2.org". The exact hosts match
1697 takes precedence over the wildcard hosts match.
1699 If path part ends with "*", it is treated as wildcard
1700 path. The wildcard path behaves differently from the
1701 normal path. For normal path, match is made around the
1702 boundary of path component separator,"/". On the other
1703 hand, the wildcard path does not take into account the
1704 path component separator. All paths which include the
1705 wildcard path without last "*" as prefix, and are
1706 strictly longer than wildcard path without last "*" are
1707 matched. "*" must match at least one character. For
1708 example, the pattern "/foo*" matches "/foo/" and
1709 "/foobar". But it does not match "/foo", or "/fo".
1711 If <PATTERN> is omitted or empty string, "/" is used as
1712 pattern, which matches all request paths (catch-all
1713 pattern). The catch-all backend must be given.
1715 When doing a match, nghttpx made some normalization to
1716 pattern, request host and path. For host part, they are
1717 converted to lower case. For path part, percent-encoded
1718 unreserved characters defined in RFC 3986 are decoded,
1719 and any dot-segments (".." and ".") are resolved and
1722 For example, -b'127.0.0.1,8080;nghttp2.org/httpbin/'
1723 matches the request host "nghttp2.org" and the request
1724 path "/httpbin/get", but does not match the request host
1725 "nghttp2.org" and the request path "/index.html".
1727 The multiple <PATTERN>s can be specified, delimiting
1728 them by ":". Specifying
1729 -b'127.0.0.1,8080;nghttp2.org:www.nghttp2.org' has the
1730 same effect to specify -b'127.0.0.1,8080;nghttp2.org'
1731 and -b'127.0.0.1,8080;www.nghttp2.org'.
1733 The backend addresses sharing same <PATTERN> are grouped
1734 together forming load balancing group.
1736 Several parameters <PARAM> are accepted after <PATTERN>.
1737 The parameters are delimited by ";". The available
1738 parameters are: "proto=<PROTO>", "tls",
1739 "sni=<SNI_HOST>", "fall=<N>", "rise=<N>",
1740 "affinity=<METHOD>", "dns", "redirect-if-not-tls",
1741 "upgrade-scheme", "mruby=<PATH>",
1742 "read-timeout=<DURATION>", "write-timeout=<DURATION>",
1743 "group=<GROUP>", "group-weight=<N>", and "weight=<N>".
1744 The parameter consists of keyword, and optionally
1745 followed by "=" and value. For example, the parameter
1746 "proto=h2" consists of the keyword "proto" and value
1747 "h2". The parameter "tls" consists of the keyword "tls"
1748 without value. Each parameter is described as follows.
1750 The backend application protocol can be specified using
1751 optional "proto" parameter, and in the form of
1752 "proto=<PROTO>". <PROTO> should be one of the following
1753 list without quotes: "h2", "http/1.1". The default
1754 value of <PROTO> is "http/1.1". Note that usually "h2"
1755 refers to HTTP/2 over TLS. But in this option, it may
1756 mean HTTP/2 over cleartext TCP unless "tls" keyword is
1759 TLS can be enabled by specifying optional "tls"
1760 parameter. TLS is not enabled by default.
1762 With "sni=<SNI_HOST>" parameter, it can override the TLS
1763 SNI field value with given <SNI_HOST>. This will
1764 default to the backend <HOST> name
1766 The feature to detect whether backend is online or
1767 offline can be enabled using optional "fall" and "rise"
1768 parameters. Using "fall=<N>" parameter, if nghttpx
1769 cannot connect to a this backend <N> times in a row,
1770 this backend is assumed to be offline, and it is
1771 excluded from load balancing. If <N> is 0, this backend
1772 never be excluded from load balancing whatever times
1773 nghttpx cannot connect to it, and this is the default.
1774 There is also "rise=<N>" parameter. After backend was
1775 excluded from load balancing group, nghttpx periodically
1776 attempts to make a connection to the failed backend, and
1777 if the connection is made successfully <N> times in a
1778 row, the backend is assumed to be online, and it is now
1779 eligible for load balancing target. If <N> is 0, a
1780 backend is permanently offline, once it goes in that
1781 state, and this is the default behaviour.
1783 The session affinity is enabled using
1784 "affinity=<METHOD>" parameter. If "ip" is given in
1785 <METHOD>, client IP based session affinity is enabled.
1786 If "cookie" is given in <METHOD>, cookie based session
1787 affinity is enabled. If "none" is given in <METHOD>,
1788 session affinity is disabled, and this is the default.
1789 The session affinity is enabled per <PATTERN>. If at
1790 least one backend has "affinity" parameter, and its
1791 <METHOD> is not "none", session affinity is enabled for
1792 all backend servers sharing the same <PATTERN>. It is
1793 advised to set "affinity" parameter to all backend
1794 explicitly if session affinity is desired. The session
1795 affinity may break if one of the backend gets
1796 unreachable, or backend settings are reloaded or
1799 If "affinity=cookie" is used, the additional
1800 configuration is required.
1801 "affinity-cookie-name=<NAME>" must be used to specify a
1802 name of cookie to use. Optionally,
1803 "affinity-cookie-path=<PATH>" can be used to specify a
1804 path which cookie is applied. The optional
1805 "affinity-cookie-secure=<SECURE>" controls the Secure
1806 attribute of a cookie. The default value is "auto", and
1807 the Secure attribute is determined by a request scheme.
1808 If a request scheme is "https", then Secure attribute is
1809 set. Otherwise, it is not set. If <SECURE> is "yes",
1810 the Secure attribute is always set. If <SECURE> is
1811 "no", the Secure attribute is always omitted.
1813 By default, name resolution of backend host name is done
1814 at start up, or reloading configuration. If "dns"
1815 parameter is given, name resolution takes place
1816 dynamically. This is useful if backend address changes
1817 frequently. If "dns" is given, name resolution of
1818 backend host name at start up, or reloading
1819 configuration is skipped.
1821 If "redirect-if-not-tls" parameter is used, the matched
1822 backend requires that frontend connection is TLS
1823 encrypted. If it isn't, nghttpx responds to the request
1824 with 308 status code, and https URI the client should
1825 use instead is included in Location header field. The
1826 port number in redirect URI is 443 by default, and can
1827 be changed using --redirect-https-port option. If at
1828 least one backend has "redirect-if-not-tls" parameter,
1829 this feature is enabled for all backend servers sharing
1830 the same <PATTERN>. It is advised to set
1831 "redirect-if-no-tls" parameter to all backends
1832 explicitly if this feature is desired.
1834 If "upgrade-scheme" parameter is used along with "tls"
1835 parameter, HTTP/2 :scheme pseudo header field is changed
1836 to "https" from "http" when forwarding a request to this
1837 particular backend. This is a workaround for a backend
1838 server which requires "https" :scheme pseudo header
1839 field on TLS encrypted connection.
1841 "mruby=<PATH>" parameter specifies a path to mruby
1842 script file which is invoked when this pattern is
1843 matched. All backends which share the same pattern must
1844 have the same mruby path.
1846 "read-timeout=<DURATION>" and "write-timeout=<DURATION>"
1847 parameters specify the read and write timeout of the
1848 backend connection when this pattern is matched. All
1849 backends which share the same pattern must have the same
1850 timeouts. If these timeouts are entirely omitted for a
1851 pattern, --backend-read-timeout and
1852 --backend-write-timeout are used.
1854 "group=<GROUP>" parameter specifies the name of group
1855 this backend address belongs to. By default, it belongs
1856 to the unnamed default group. The name of group is
1857 unique per pattern. "group-weight=<N>" parameter
1858 specifies the weight of the group. The higher weight
1859 gets more frequently selected by the load balancing
1860 algorithm. <N> must be [1, 256] inclusive. The weight
1861 8 has 4 times more weight than 2. <N> must be the same
1862 for all addresses which share the same <GROUP>. If
1863 "group-weight" is omitted in an address, but the other
1864 address which belongs to the same group specifies
1865 "group-weight", its weight is used. If no
1866 "group-weight" is specified for all addresses, the
1867 weight of a group becomes 1. "group" and "group-weight"
1868 are ignored if session affinity is enabled.
1870 "weight=<N>" parameter specifies the weight of the
1871 backend address inside a group which this address
1872 belongs to. The higher weight gets more frequently
1873 selected by the load balancing algorithm. <N> must be
1874 [1, 256] inclusive. The weight 8 has 4 times more
1875 weight than weight 2. If this parameter is omitted,
1876 weight becomes 1. "weight" is ignored if session
1877 affinity is enabled.
1879 Since ";" and ":" are used as delimiter, <PATTERN> must
1880 not contain these characters. Since ";" has special
1881 meaning in shell, the option value must be quoted.
1884 << DEFAULT_DOWNSTREAM_HOST << "," << DEFAULT_DOWNSTREAM_PORT << R"(
1885 -f, --frontend=(<HOST>,<PORT>|unix:<PATH>)[[;<PARAM>]...]
1886 Set frontend host and port. If <HOST> is '*', it
1887 assumes all addresses including both IPv4 and IPv6.
1888 UNIX domain socket can be specified by prefixing path
1889 name with "unix:" (e.g., unix:/var/run/nghttpx.sock).
1890 This option can be used multiple times to listen to
1893 This option can take 0 or more parameters, which are
1894 described below. Note that "api" and "healthmon"
1895 parameters are mutually exclusive.
1897 Optionally, TLS can be disabled by specifying "no-tls"
1898 parameter. TLS is enabled by default.
1900 If "sni-fwd" parameter is used, when performing a match
1901 to select a backend server, SNI host name received from
1902 the client is used instead of the request host. See
1903 --backend option about the pattern match.
1905 To make this frontend as API endpoint, specify "api"
1906 parameter. This is disabled by default. It is
1907 important to limit the access to the API frontend.
1908 Otherwise, someone may change the backend server, and
1909 break your services, or expose confidential information
1910 to the outside the world.
1912 To make this frontend as health monitor endpoint,
1913 specify "healthmon" parameter. This is disabled by
1914 default. Any requests which come through this address
1915 are replied with 200 HTTP status, without no body.
1917 To accept PROXY protocol version 1 and 2 on frontend
1918 connection, specify "proxyproto" parameter. This is
1919 disabled by default.
1923 Set listen backlog size.
1925 << config->conn.listener.backlog << R"(
1926 --backend-address-family=(auto|IPv4|IPv6)
1927 Specify address family of backend connections. If
1928 "auto" is given, both IPv4 and IPv6 are considered. If
1929 "IPv4" is given, only IPv4 address is considered. If
1930 "IPv6" is given, only IPv6 address is considered.
1932 --backend-http-proxy-uri=<URI>
1933 Specify proxy URI in the form
1934 http://[<USER>:<PASS>@]<PROXY>:<PORT>. If a proxy
1935 requires authentication, specify <USER> and <PASS>.
1936 Note that they must be properly percent-encoded. This
1937 proxy is used when the backend connection is HTTP/2.
1938 First, make a CONNECT request to the proxy and it
1939 connects to the backend on behalf of nghttpx. This
1940 forms tunnel. After that, nghttpx performs SSL/TLS
1941 handshake with the downstream through the tunnel. The
1942 timeouts when connecting and making CONNECT request can
1943 be specified by --backend-read-timeout and
1944 --backend-write-timeout options.
1948 Set the number of worker threads.
1950 << config->num_worker << R"(
1952 Run everything in one thread inside the worker process.
1953 This feature is provided for better debugging
1954 experience, or for the platforms which lack thread
1955 support. If threading is disabled, this option is
1958 Set maximum average read rate on frontend connection.
1959 Setting 0 to this option means read rate is unlimited.
1961 << config->conn.upstream.ratelimit.read.rate << R"(
1963 Set maximum read burst size on frontend connection.
1964 Setting 0 to this option means read burst size is
1967 << config->conn.upstream.ratelimit.read.burst << R"(
1969 Set maximum average write rate on frontend connection.
1970 Setting 0 to this option means write rate is unlimited.
1972 << config->conn.upstream.ratelimit.write.rate << R"(
1973 --write-burst=<SIZE>
1974 Set maximum write burst size on frontend connection.
1975 Setting 0 to this option means write burst size is
1978 << config->conn.upstream.ratelimit.write.burst << R"(
1979 --worker-read-rate=<SIZE>
1980 Set maximum average read rate on frontend connection per
1981 worker. Setting 0 to this option means read rate is
1982 unlimited. Not implemented yet.
1984 --worker-read-burst=<SIZE>
1985 Set maximum read burst size on frontend connection per
1986 worker. Setting 0 to this option means read burst size
1987 is unlimited. Not implemented yet.
1989 --worker-write-rate=<SIZE>
1990 Set maximum average write rate on frontend connection
1991 per worker. Setting 0 to this option means write rate
1992 is unlimited. Not implemented yet.
1994 --worker-write-burst=<SIZE>
1995 Set maximum write burst size on frontend connection per
1996 worker. Setting 0 to this option means write burst size
1997 is unlimited. Not implemented yet.
1999 --worker-frontend-connections=<N>
2000 Set maximum number of simultaneous connections frontend
2001 accepts. Setting 0 means unlimited.
2003 << config->conn.upstream.worker_connections << R"(
2004 --backend-connections-per-host=<N>
2005 Set maximum number of backend concurrent connections
2006 (and/or streams in case of HTTP/2) per origin host.
2007 This option is meaningful when --http2-proxy option is
2008 used. The origin host is determined by authority
2009 portion of request URI (or :authority header field for
2010 HTTP/2). To limit the number of connections per
2011 frontend for default mode, use
2012 --backend-connections-per-frontend.
2014 << config->conn.downstream->connections_per_host << R"(
2015 --backend-connections-per-frontend=<N>
2016 Set maximum number of backend concurrent connections
2017 (and/or streams in case of HTTP/2) per frontend. This
2018 option is only used for default mode. 0 means
2019 unlimited. To limit the number of connections per host
2020 with --http2-proxy option, use
2021 --backend-connections-per-host.
2023 << config->conn.downstream->connections_per_frontend << R"(
2025 Set maximum number of open files (RLIMIT_NOFILE) to <N>.
2026 If 0 is given, nghttpx does not set the limit.
2028 << config->rlimit_nofile << R"(
2029 --backend-request-buffer=<SIZE>
2030 Set buffer size used to store backend request.
2032 << util::utos_unit(config->conn.downstream->request_buffer_size) << R"(
2033 --backend-response-buffer=<SIZE>
2034 Set buffer size used to store backend response.
2036 << util::utos_unit(config->conn.downstream->response_buffer_size) << R"(
2038 Enables "TCP Fast Open" for the listening socket and
2039 limits the maximum length for the queue of connections
2040 that have not yet completed the three-way handshake. If
2041 value is 0 then fast open is disabled.
2043 << config->conn.listener.fastopen << R"(
2044 --no-kqueue Don't use kqueue. This option is only applicable for
2045 the platforms which have kqueue. For other platforms,
2046 this option will be simply ignored.
2049 --frontend-http2-read-timeout=<DURATION>
2050 Specify read timeout for HTTP/2 frontend connection.
2052 << util::duration_str(config->conn.upstream.timeout.http2_read) << R"(
2053 --frontend-read-timeout=<DURATION>
2054 Specify read timeout for HTTP/1.1 frontend connection.
2056 << util::duration_str(config->conn.upstream.timeout.read) << R"(
2057 --frontend-write-timeout=<DURATION>
2058 Specify write timeout for all frontend connections.
2060 << util::duration_str(config->conn.upstream.timeout.write) << R"(
2061 --frontend-keep-alive-timeout=<DURATION>
2062 Specify keep-alive timeout for frontend HTTP/1
2065 << util::duration_str(config->conn.upstream.timeout.idle_read) << R"(
2066 --stream-read-timeout=<DURATION>
2067 Specify read timeout for HTTP/2 streams. 0 means no
2070 << util::duration_str(config->http2.timeout.stream_read) << R"(
2071 --stream-write-timeout=<DURATION>
2072 Specify write timeout for HTTP/2 streams. 0 means no
2075 << util::duration_str(config->http2.timeout.stream_write) << R"(
2076 --backend-read-timeout=<DURATION>
2077 Specify read timeout for backend connection.
2079 << util::duration_str(config->conn.downstream->timeout.read) << R"(
2080 --backend-write-timeout=<DURATION>
2081 Specify write timeout for backend connection.
2083 << util::duration_str(config->conn.downstream->timeout.write) << R"(
2084 --backend-connect-timeout=<DURATION>
2085 Specify timeout before establishing TCP connection to
2088 << util::duration_str(config->conn.downstream->timeout.connect) << R"(
2089 --backend-keep-alive-timeout=<DURATION>
2090 Specify keep-alive timeout for backend HTTP/1
2093 << util::duration_str(config->conn.downstream->timeout.idle_read) << R"(
2094 --listener-disable-timeout=<DURATION>
2095 After accepting connection failed, connection listener
2096 is disabled for a given amount of time. Specifying 0
2097 disables this feature.
2099 << util::duration_str(config->conn.listener.timeout.sleep) << R"(
2100 --frontend-http2-setting-timeout=<DURATION>
2101 Specify timeout before SETTINGS ACK is received from
2104 << util::duration_str(config->http2.upstream.timeout.settings) << R"(
2105 --backend-http2-settings-timeout=<DURATION>
2106 Specify timeout before SETTINGS ACK is received from
2109 << util::duration_str(config->http2.downstream.timeout.settings) << R"(
2110 --backend-max-backoff=<DURATION>
2111 Specify maximum backoff interval. This is used when
2112 doing health check against offline backend (see "fail"
2113 parameter in --backend option). It is also used to
2114 limit the maximum interval to temporarily disable
2115 backend when nghttpx failed to connect to it. These
2116 intervals are calculated using exponential backoff, and
2117 consecutive failed attempts increase the interval. This
2118 option caps its maximum value.
2120 << util::duration_str(config->conn.downstream->timeout.max_backoff) << R"(
2124 Set allowed cipher list for frontend connection. The
2125 format of the string is described in OpenSSL ciphers(1).
2126 This option sets cipher suites for TLSv1.2 or earlier.
2127 Use --tls13-ciphers for TLSv1.3.
2129 << config->tls.ciphers << R"(
2130 --tls13-ciphers=<SUITE>
2131 Set allowed cipher list for frontend connection. The
2132 format of the string is described in OpenSSL ciphers(1).
2133 This option sets cipher suites for TLSv1.3. Use
2134 --ciphers for TLSv1.2 or earlier.
2136 << config->tls.tls13_ciphers << R"(
2137 --client-ciphers=<SUITE>
2138 Set allowed cipher list for backend connection. The
2139 format of the string is described in OpenSSL ciphers(1).
2140 This option sets cipher suites for TLSv1.2 or earlier.
2141 Use --tls13-client-ciphers for TLSv1.3.
2143 << config->tls.client.ciphers << R"(
2144 --tls13-client-ciphers=<SUITE>
2145 Set allowed cipher list for backend connection. The
2146 format of the string is described in OpenSSL ciphers(1).
2147 This option sets cipher suites for TLSv1.3. Use
2148 --tls13-client-ciphers for TLSv1.2 or earlier.
2150 << config->tls.client.tls13_ciphers << R"(
2151 --ecdh-curves=<LIST>
2152 Set supported curve list for frontend connections.
2153 <LIST> is a colon separated list of curve NID or names
2154 in the preference order. The supported curves depend on
2155 the linked OpenSSL library. This function requires
2158 << config->tls.ecdh_curves << R"(
2160 Don't verify backend server's certificate if TLS is
2161 enabled for backend connections.
2163 Set path to trusted CA certificate file. It is used in
2164 backend TLS connections to verify peer's certificate.
2165 It is also used to verify OCSP response from the script
2166 set by --fetch-ocsp-response-file. The file must be in
2167 PEM format. It can contain multiple certificates. If
2168 the linked OpenSSL is configured to load system wide
2169 certificates, they are loaded at startup regardless of
2171 --private-key-passwd-file=<PATH>
2172 Path to file that contains password for the server's
2173 private key. If none is given and the private key is
2174 password protected it'll be requested interactively.
2175 --subcert=<KEYPATH>:<CERTPATH>[[;<PARAM>]...]
2176 Specify additional certificate and private key file.
2177 nghttpx will choose certificates based on the hostname
2178 indicated by client using TLS SNI extension. If nghttpx
2179 is built with OpenSSL >= 1.0.2, the shared elliptic
2180 curves (e.g., P-256) between client and server are also
2181 taken into consideration. This allows nghttpx to send
2182 ECDSA certificate to modern clients, while sending RSA
2183 based certificate to older clients. This option can be
2184 used multiple times. To make OCSP stapling work,
2185 <CERTPATH> must be absolute path.
2187 Additional parameter can be specified in <PARAM>. The
2188 available <PARAM> is "sct-dir=<DIR>".
2190 "sct-dir=<DIR>" specifies the path to directory which
2191 contains *.sct files for TLS
2192 signed_certificate_timestamp extension (RFC 6962). This
2193 feature requires OpenSSL >= 1.0.2. See also
2194 --tls-sct-dir option.
2195 --dh-param-file=<PATH>
2196 Path to file that contains DH parameters in PEM format.
2197 Without this option, DHE cipher suites are not
2200 Comma delimited list of ALPN protocol identifier sorted
2201 in the order of preference. That means most desirable
2202 protocol comes first. This is used in both ALPN and
2203 NPN. The parameter must be delimited by a single comma
2204 only and any white spaces are treated as a part of
2210 Require and verify client certificate.
2211 --verify-client-cacert=<PATH>
2212 Path to file that contains CA certificates to verify
2213 client certificate. The file must be in PEM format. It
2214 can contain multiple certificates.
2215 --verify-client-tolerate-expired
2216 Accept expired client certificate. Operator should
2217 handle the expired client certificate by some means
2218 (e.g., mruby script). Otherwise, this option might
2219 cause a security risk.
2220 --client-private-key-file=<PATH>
2221 Path to file that contains client private key used in
2222 backend client authentication.
2223 --client-cert-file=<PATH>
2224 Path to file that contains client certificate used in
2225 backend client authentication.
2226 --tls-min-proto-version=<VER>
2227 Specify minimum SSL/TLS protocol. The name matching is
2228 done in case-insensitive manner. The versions between
2229 --tls-min-proto-version and --tls-max-proto-version are
2230 enabled. If the protocol list advertised by client does
2231 not overlap this range, you will receive the error
2232 message "unknown protocol". If a protocol version lower
2233 than TLSv1.2 is specified, make sure that the compatible
2234 ciphers are included in --ciphers option. The default
2235 cipher list only includes ciphers compatible with
2236 TLSv1.2 or above. The available versions are:
2238 #ifdef TLS1_3_VERSION
2240 #endif // TLS1_3_VERSION
2241 "TLSv1.2, TLSv1.1, and TLSv1.0"
2244 << DEFAULT_TLS_MIN_PROTO_VERSION
2246 --tls-max-proto-version=<VER>
2247 Specify maximum SSL/TLS protocol. The name matching is
2248 done in case-insensitive manner. The versions between
2249 --tls-min-proto-version and --tls-max-proto-version are
2250 enabled. If the protocol list advertised by client does
2251 not overlap this range, you will receive the error
2252 message "unknown protocol". The available versions are:
2254 #ifdef TLS1_3_VERSION
2256 #endif // TLS1_3_VERSION
2257 "TLSv1.2, TLSv1.1, and TLSv1.0"
2260 << DEFAULT_TLS_MAX_PROTO_VERSION << R"(
2261 --tls-ticket-key-file=<PATH>
2262 Path to file that contains random data to construct TLS
2263 session ticket parameters. If aes-128-cbc is given in
2264 --tls-ticket-key-cipher, the file must contain exactly
2265 48 bytes. If aes-256-cbc is given in
2266 --tls-ticket-key-cipher, the file must contain exactly
2267 80 bytes. This options can be used repeatedly to
2268 specify multiple ticket parameters. If several files
2269 are given, only the first key is used to encrypt TLS
2270 session tickets. Other keys are accepted but server
2271 will issue new session ticket with first key. This
2272 allows session key rotation. Please note that key
2273 rotation does not occur automatically. User should
2274 rearrange files or change options values and restart
2275 nghttpx gracefully. If opening or reading given file
2276 fails, all loaded keys are discarded and it is treated
2277 as if none of this option is given. If this option is
2278 not given or an error occurred while opening or reading
2279 a file, key is generated every 1 hour internally and
2280 they are valid for 12 hours. This is recommended if
2281 ticket key sharing between nghttpx instances is not
2283 --tls-ticket-key-memcached=<HOST>,<PORT>[;tls]
2284 Specify address of memcached server to get TLS ticket
2285 keys for session resumption. This enables shared TLS
2286 ticket key between multiple nghttpx instances. nghttpx
2287 does not set TLS ticket key to memcached. The external
2288 ticket key generator is required. nghttpx just gets TLS
2289 ticket keys from memcached, and use them, possibly
2290 replacing current set of keys. It is up to extern TLS
2291 ticket key generator to rotate keys frequently. See
2292 "TLS SESSION TICKET RESUMPTION" section in manual page
2293 to know the data format in memcached entry. Optionally,
2294 memcached connection can be encrypted with TLS by
2295 specifying "tls" parameter.
2296 --tls-ticket-key-memcached-address-family=(auto|IPv4|IPv6)
2297 Specify address family of memcached connections to get
2298 TLS ticket keys. If "auto" is given, both IPv4 and IPv6
2299 are considered. If "IPv4" is given, only IPv4 address
2300 is considered. If "IPv6" is given, only IPv6 address is
2303 --tls-ticket-key-memcached-interval=<DURATION>
2304 Set interval to get TLS ticket keys from memcached.
2306 << util::duration_str(config->tls.ticket.memcached.interval) << R"(
2307 --tls-ticket-key-memcached-max-retry=<N>
2308 Set maximum number of consecutive retries before
2309 abandoning TLS ticket key retrieval. If this number is
2310 reached, the attempt is considered as failure, and
2311 "failure" count is incremented by 1, which contributed
2312 to the value controlled
2313 --tls-ticket-key-memcached-max-fail option.
2315 << config->tls.ticket.memcached.max_retry << R"(
2316 --tls-ticket-key-memcached-max-fail=<N>
2317 Set maximum number of consecutive failure before
2318 disabling TLS ticket until next scheduled key retrieval.
2320 << config->tls.ticket.memcached.max_fail << R"(
2321 --tls-ticket-key-cipher=<CIPHER>
2322 Specify cipher to encrypt TLS session ticket. Specify
2323 either aes-128-cbc or aes-256-cbc. By default,
2324 aes-128-cbc is used.
2325 --tls-ticket-key-memcached-cert-file=<PATH>
2326 Path to client certificate for memcached connections to
2327 get TLS ticket keys.
2328 --tls-ticket-key-memcached-private-key-file=<PATH>
2329 Path to client private key for memcached connections to
2330 get TLS ticket keys.
2331 --fetch-ocsp-response-file=<PATH>
2332 Path to fetch-ocsp-response script file. It should be
2335 << config->tls.ocsp.fetch_ocsp_response_file << R"(
2336 --ocsp-update-interval=<DURATION>
2337 Set interval to update OCSP response cache.
2339 << util::duration_str(config->tls.ocsp.update_interval) << R"(
2341 Start accepting connections after initial attempts to
2342 get OCSP responses finish. It does not matter some of
2343 the attempts fail. This feature is useful if OCSP
2344 responses must be available before accepting
2347 nghttpx does not verify OCSP response.
2348 --no-ocsp Disable OCSP stapling.
2349 --tls-session-cache-memcached=<HOST>,<PORT>[;tls]
2350 Specify address of memcached server to store session
2351 cache. This enables shared session cache between
2352 multiple nghttpx instances. Optionally, memcached
2353 connection can be encrypted with TLS by specifying "tls"
2355 --tls-session-cache-memcached-address-family=(auto|IPv4|IPv6)
2356 Specify address family of memcached connections to store
2357 session cache. If "auto" is given, both IPv4 and IPv6
2358 are considered. If "IPv4" is given, only IPv4 address
2359 is considered. If "IPv6" is given, only IPv6 address is
2362 --tls-session-cache-memcached-cert-file=<PATH>
2363 Path to client certificate for memcached connections to
2364 store session cache.
2365 --tls-session-cache-memcached-private-key-file=<PATH>
2366 Path to client private key for memcached connections to
2367 store session cache.
2368 --tls-dyn-rec-warmup-threshold=<SIZE>
2369 Specify the threshold size for TLS dynamic record size
2370 behaviour. During a TLS session, after the threshold
2371 number of bytes have been written, the TLS record size
2372 will be increased to the maximum allowed (16K). The max
2373 record size will continue to be used on the active TLS
2374 session. After --tls-dyn-rec-idle-timeout has elapsed,
2375 the record size is reduced to 1300 bytes. Specify 0 to
2376 always use the maximum record size, regardless of idle
2377 period. This behaviour applies to all TLS based
2378 frontends, and TLS HTTP/2 backends.
2380 << util::utos_unit(config->tls.dyn_rec.warmup_threshold) << R"(
2381 --tls-dyn-rec-idle-timeout=<DURATION>
2382 Specify TLS dynamic record size behaviour timeout. See
2383 --tls-dyn-rec-warmup-threshold for more information.
2384 This behaviour applies to all TLS based frontends, and
2385 TLS HTTP/2 backends.
2387 << util::duration_str(config->tls.dyn_rec.idle_timeout) << R"(
2388 --no-http2-cipher-black-list
2389 Allow black listed cipher suite on frontend HTTP/2
2391 https://tools.ietf.org/html/rfc7540#appendix-A for the
2392 complete HTTP/2 cipher suites black list.
2393 --client-no-http2-cipher-black-list
2394 Allow black listed cipher suite on backend HTTP/2
2396 https://tools.ietf.org/html/rfc7540#appendix-A for the
2397 complete HTTP/2 cipher suites black list.
2399 Specifies the directory where *.sct files exist. All
2400 *.sct files in <DIR> are read, and sent as
2401 extension_data of TLS signed_certificate_timestamp (RFC
2402 6962) to client. These *.sct files are for the
2403 certificate specified in positional command-line
2404 argument <CERT>, or certificate option in configuration
2405 file. For additional certificates, use --subcert
2406 option. This option requires OpenSSL >= 1.0.2.
2407 --psk-secrets=<PATH>
2408 Read list of PSK identity and secrets from <PATH>. This
2409 is used for frontend connection. The each line of input
2410 file is formatted as <identity>:<hex-secret>, where
2411 <identity> is PSK identity, and <hex-secret> is secret
2412 in hex. An empty line, and line which starts with '#'
2413 are skipped. The default enabled cipher list might not
2414 contain any PSK cipher suite. In that case, desired PSK
2415 cipher suites must be enabled using --ciphers option.
2416 The desired PSK cipher suite may be black listed by
2417 HTTP/2. To use those cipher suites with HTTP/2,
2418 consider to use --no-http2-cipher-black-list option.
2419 But be aware its implications.
2420 --client-psk-secrets=<PATH>
2421 Read PSK identity and secrets from <PATH>. This is used
2422 for backend connection. The each line of input file is
2423 formatted as <identity>:<hex-secret>, where <identity>
2424 is PSK identity, and <hex-secret> is secret in hex. An
2425 empty line, and line which starts with '#' are skipped.
2426 The first identity and secret pair encountered is used.
2427 The default enabled cipher list might not contain any
2428 PSK cipher suite. In that case, desired PSK cipher
2429 suites must be enabled using --client-ciphers option.
2430 The desired PSK cipher suite may be black listed by
2431 HTTP/2. To use those cipher suites with HTTP/2,
2432 consider to use --client-no-http2-cipher-black-list
2433 option. But be aware its implications.
2434 --tls-no-postpone-early-data
2435 By default, nghttpx postpones forwarding HTTP requests
2436 sent in early data, including those sent in partially in
2437 it, until TLS handshake finishes. If all backend server
2438 recognizes "Early-Data" header field, using this option
2439 makes nghttpx not postpone forwarding request and get
2440 full potential of 0-RTT data.
2441 --tls-max-early-data=<SIZE>
2442 Sets the maximum amount of 0-RTT data that server
2445 << util::utos_unit(config->tls.max_early_data) << R"(
2448 -c, --frontend-http2-max-concurrent-streams=<N>
2449 Set the maximum number of the concurrent streams in one
2450 frontend HTTP/2 session.
2452 << config->http2.upstream.max_concurrent_streams << R"(
2453 --backend-http2-max-concurrent-streams=<N>
2454 Set the maximum number of the concurrent streams in one
2455 backend HTTP/2 session. This sets maximum number of
2456 concurrent opened pushed streams. The maximum number of
2457 concurrent requests are set by a remote server.
2459 << config->http2.downstream.max_concurrent_streams << R"(
2460 --frontend-http2-window-size=<SIZE>
2461 Sets the per-stream initial window size of HTTP/2
2462 frontend connection.
2464 << config->http2.upstream.window_size << R"(
2465 --frontend-http2-connection-window-size=<SIZE>
2466 Sets the per-connection window size of HTTP/2 frontend
2469 << config->http2.upstream.connection_window_size << R"(
2470 --backend-http2-window-size=<SIZE>
2471 Sets the initial window size of HTTP/2 backend
2474 << config->http2.downstream.window_size << R"(
2475 --backend-http2-connection-window-size=<SIZE>
2476 Sets the per-connection window size of HTTP/2 backend
2479 << config->http2.downstream.connection_window_size << R"(
2480 --http2-no-cookie-crumbling
2481 Don't crumble cookie header field.
2483 Add at most <N> bytes to a HTTP/2 frame payload as
2484 padding. Specify 0 to disable padding. This option is
2485 meant for debugging purpose and not intended to enhance
2488 Disable HTTP/2 server push. Server push is supported by
2489 default mode and HTTP/2 frontend via Link header field.
2490 It is also supported if both frontend and backend are
2491 HTTP/2 in default mode. In this case, server push from
2492 backend session is relayed to frontend, and server push
2493 via Link header field is also supported.
2494 --frontend-http2-optimize-write-buffer-size
2495 (Experimental) Enable write buffer size optimization in
2496 frontend HTTP/2 TLS connection. This optimization aims
2497 to reduce write buffer size so that it only contains
2498 bytes which can send immediately. This makes server
2499 more responsive to prioritized HTTP/2 stream because the
2500 buffering of lower priority stream is reduced. This
2501 option is only effective on recent Linux platform.
2502 --frontend-http2-optimize-window-size
2503 (Experimental) Automatically tune connection level
2504 window size of frontend HTTP/2 TLS connection. If this
2505 feature is enabled, connection window size starts with
2506 the default window size, 65535 bytes. nghttpx
2507 automatically adjusts connection window size based on
2508 TCP receiving window size. The maximum window size is
2509 capped by the value specified by
2510 --frontend-http2-connection-window-size. Since the
2511 stream is subject to stream level window size, it should
2512 be adjusted using --frontend-http2-window-size option as
2513 well. This option is only effective on recent Linux
2515 --frontend-http2-encoder-dynamic-table-size=<SIZE>
2516 Specify the maximum dynamic table size of HPACK encoder
2517 in the frontend HTTP/2 connection. The decoder (client)
2518 specifies the maximum dynamic table size it accepts.
2519 Then the negotiated dynamic table size is the minimum of
2520 this option value and the value which client specified.
2522 << util::utos_unit(config->http2.upstream.encoder_dynamic_table_size)
2524 --frontend-http2-decoder-dynamic-table-size=<SIZE>
2525 Specify the maximum dynamic table size of HPACK decoder
2526 in the frontend HTTP/2 connection.
2528 << util::utos_unit(config->http2.upstream.decoder_dynamic_table_size)
2530 --backend-http2-encoder-dynamic-table-size=<SIZE>
2531 Specify the maximum dynamic table size of HPACK encoder
2532 in the backend HTTP/2 connection. The decoder (backend)
2533 specifies the maximum dynamic table size it accepts.
2534 Then the negotiated dynamic table size is the minimum of
2535 this option value and the value which backend specified.
2537 << util::utos_unit(config->http2.downstream.encoder_dynamic_table_size)
2539 --backend-http2-decoder-dynamic-table-size=<SIZE>
2540 Specify the maximum dynamic table size of HPACK decoder
2541 in the backend HTTP/2 connection.
2543 << util::utos_unit(config->http2.downstream.decoder_dynamic_table_size)
2548 Accept HTTP/2, and HTTP/1.1 over SSL/TLS. "no-tls"
2549 parameter is used in --frontend option, accept HTTP/2
2550 and HTTP/1.1 over cleartext TCP. The incoming HTTP/1.1
2551 connection can be upgraded to HTTP/2 through HTTP
2554 Like default mode, but enable forward proxy. This is so
2555 called HTTP/2 proxy mode.
2558 -L, --log-level=<LEVEL>
2559 Set the severity level of log output. <LEVEL> must be
2560 one of INFO, NOTICE, WARN, ERROR and FATAL.
2562 --accesslog-file=<PATH>
2563 Set path to write access log. To reopen file, send USR1
2566 Send access log to syslog. If this option is used,
2567 --accesslog-file option is ignored.
2568 --accesslog-format=<FORMAT>
2569 Specify format string for access log. The default
2570 format is combined format. The following variables are
2573 * $remote_addr: client IP address.
2574 * $time_local: local time in Common Log format.
2575 * $time_iso8601: local time in ISO 8601 format.
2576 * $request: HTTP request line.
2577 * $status: HTTP response status code.
2578 * $body_bytes_sent: the number of bytes sent to client
2580 * $http_<VAR>: value of HTTP request header <VAR> where
2581 '_' in <VAR> is replaced with '-'.
2582 * $remote_port: client port.
2583 * $server_port: server port.
2584 * $request_time: request processing time in seconds with
2585 milliseconds resolution.
2586 * $pid: PID of the running process.
2587 * $alpn: ALPN identifier of the protocol which generates
2588 the response. For HTTP/1, ALPN is always http/1.1,
2589 regardless of minor version.
2590 * $tls_cipher: cipher used for SSL/TLS connection.
2591 * $tls_client_fingerprint_sha256: SHA-256 fingerprint of
2593 * $tls_client_fingerprint_sha1: SHA-1 fingerprint of
2595 * $tls_client_subject_name: subject name in client
2597 * $tls_client_issuer_name: issuer name in client
2599 * $tls_client_serial: serial number in client
2601 * $tls_protocol: protocol for SSL/TLS connection.
2602 * $tls_session_id: session ID for SSL/TLS connection.
2603 * $tls_session_reused: "r" if SSL/TLS session was
2604 reused. Otherwise, "."
2605 * $tls_sni: SNI server name for SSL/TLS connection.
2606 * $backend_host: backend host used to fulfill the
2607 request. "-" if backend host is not available.
2608 * $backend_port: backend port used to fulfill the
2609 request. "-" if backend host is not available.
2611 The variable can be enclosed by "{" and "}" for
2612 disambiguation (e.g., ${remote_addr}).
2615 << DEFAULT_ACCESSLOG_FORMAT << R"(
2616 --accesslog-write-early
2617 Write access log when response header fields are
2618 received from backend rather than when request
2619 transaction finishes.
2620 --errorlog-file=<PATH>
2621 Set path to write error log. To reopen file, send USR1
2622 signal to nghttpx. stderr will be redirected to the
2623 error log file unless --errorlog-syslog is used.
2625 << config->logging.error.file << R"(
2627 Send error log to syslog. If this option is used,
2628 --errorlog-file option is ignored.
2629 --syslog-facility=<FACILITY>
2630 Set syslog facility to <FACILITY>.
2632 << str_syslog_facility(config->logging.syslog_facility) << R"(
2635 --add-x-forwarded-for
2636 Append X-Forwarded-For header field to the downstream
2638 --strip-incoming-x-forwarded-for
2639 Strip X-Forwarded-For header field from inbound client
2641 --no-add-x-forwarded-proto
2642 Don't append additional X-Forwarded-Proto header field
2643 to the backend request. If inbound client sets
2644 X-Forwarded-Proto, and
2645 --no-strip-incoming-x-forwarded-proto option is used,
2646 they are passed to the backend.
2647 --no-strip-incoming-x-forwarded-proto
2648 Don't strip X-Forwarded-Proto header field from inbound
2650 --add-forwarded=<LIST>
2651 Append RFC 7239 Forwarded header field with parameters
2652 specified in comma delimited list <LIST>. The supported
2653 parameters are "by", "for", "host", and "proto". By
2654 default, the value of "by" and "for" parameters are
2655 obfuscated string. See --forwarded-by and
2656 --forwarded-for options respectively. Note that nghttpx
2657 does not translate non-standard X-Forwarded-* header
2658 fields into Forwarded header field, and vice versa.
2659 --strip-incoming-forwarded
2660 Strip Forwarded header field from inbound client
2662 --forwarded-by=(obfuscated|ip|<VALUE>)
2663 Specify the parameter value sent out with "by" parameter
2664 of Forwarded header field. If "obfuscated" is given,
2665 the string is randomly generated at startup. If "ip" is
2666 given, the interface address of the connection,
2667 including port number, is sent with "by" parameter. In
2668 case of UNIX domain socket, "localhost" is used instead
2669 of address and port. User can also specify the static
2670 obfuscated string. The limitation is that it must start
2671 with "_", and only consists of character set
2672 [A-Za-z0-9._-], as described in RFC 7239.
2674 --forwarded-for=(obfuscated|ip)
2675 Specify the parameter value sent out with "for"
2676 parameter of Forwarded header field. If "obfuscated" is
2677 given, the string is randomly generated for each client
2678 connection. If "ip" is given, the remote client address
2679 of the connection, without port number, is sent with
2680 "for" parameter. In case of UNIX domain socket,
2681 "localhost" is used instead of address.
2683 --no-via Don't append to Via header field. If Via header field
2684 is received, it is left unaltered.
2685 --no-strip-incoming-early-data
2686 Don't strip Early-Data header field from inbound client
2688 --no-location-rewrite
2689 Don't rewrite location header field in default mode.
2690 When --http2-proxy is used, location header field will
2691 not be altered regardless of this option.
2693 Rewrite host and :authority header fields in default
2694 mode. When --http2-proxy is used, these headers will
2695 not be altered regardless of this option.
2696 --altsvc=<PROTOID,PORT[,HOST,[ORIGIN]]>
2697 Specify protocol ID, port, host and origin of
2698 alternative service. <HOST> and <ORIGIN> are optional.
2699 They are advertised in alt-svc header field only in
2700 HTTP/1.1 frontend. This option can be used multiple
2701 times to specify multiple alternative services.
2702 Example: --altsvc=h2,443
2703 --add-request-header=<HEADER>
2704 Specify additional header field to add to request header
2705 set. This option just appends header field and won't
2706 replace anything already set. This option can be used
2707 several times to specify multiple header fields.
2708 Example: --add-request-header="foo: bar"
2709 --add-response-header=<HEADER>
2710 Specify additional header field to add to response
2711 header set. This option just appends header field and
2712 won't replace anything already set. This option can be
2713 used several times to specify multiple header fields.
2714 Example: --add-response-header="foo: bar"
2715 --request-header-field-buffer=<SIZE>
2716 Set maximum buffer size for incoming HTTP request header
2717 field list. This is the sum of header name and value in
2718 bytes. If trailer fields exist, they are counted
2719 towards this number.
2721 << util::utos_unit(config->http.request_header_field_buffer) << R"(
2722 --max-request-header-fields=<N>
2723 Set maximum number of incoming HTTP request header
2724 fields. If trailer fields exist, they are counted
2725 towards this number.
2727 << config->http.max_request_header_fields << R"(
2728 --response-header-field-buffer=<SIZE>
2729 Set maximum buffer size for incoming HTTP response
2730 header field list. This is the sum of header name and
2731 value in bytes. If trailer fields exist, they are
2732 counted towards this number.
2734 << util::utos_unit(config->http.response_header_field_buffer) << R"(
2735 --max-response-header-fields=<N>
2736 Set maximum number of incoming HTTP response header
2737 fields. If trailer fields exist, they are counted
2738 towards this number.
2740 << config->http.max_response_header_fields << R"(
2741 --error-page=(<CODE>|*)=<PATH>
2742 Set file path to custom error page served when nghttpx
2743 originally generates HTTP error status code <CODE>.
2744 <CODE> must be greater than or equal to 400, and at most
2745 599. If "*" is used instead of <CODE>, it matches all
2746 HTTP status code. If error status code comes from
2747 backend server, the custom error pages are not used.
2748 --server-name=<NAME>
2749 Change server response header field value to <NAME>.
2751 << config->http.server_name << R"(
2753 Don't rewrite server header field in default mode. When
2754 --http2-proxy is used, these headers will not be altered
2755 regardless of this option.
2756 --redirect-https-port=<PORT>
2757 Specify the port number which appears in Location header
2758 field when redirect to HTTPS URI is made due to
2759 "redirect-if-not-tls" parameter in --backend option.
2761 << config->http.redirect_https_port << R"(
2764 --api-max-request-body=<SIZE>
2765 Set the maximum size of request body for API request.
2767 << util::utos_unit(config->api.max_request_body) << R"(
2770 --dns-cache-timeout=<DURATION>
2771 Set duration that cached DNS results remain valid. Note
2772 that nghttpx caches the unsuccessful results as well.
2774 << util::duration_str(config->dns.timeout.cache) << R"(
2775 --dns-lookup-timeout=<DURATION>
2776 Set timeout that DNS server is given to respond to the
2777 initial DNS query. For the 2nd and later queries,
2778 server is given time based on this timeout, and it is
2781 << util::duration_str(config->dns.timeout.lookup) << R"(
2783 Set the number of DNS query before nghttpx gives up name
2786 << config->dns.max_try << R"(
2787 --frontend-max-requests=<N>
2788 The number of requests that single frontend connection
2789 can process. For HTTP/2, this is the number of streams
2790 in one HTTP/2 connection. For HTTP/1, this is the
2791 number of keep alive requests. This is hint to nghttpx,
2792 and it may allow additional few requests. The default
2796 --frontend-http2-dump-request-header=<PATH>
2797 Dumps request headers received by HTTP/2 frontend to the
2798 file denoted in <PATH>. The output is done in HTTP/1
2799 header field format and each header block is followed by
2800 an empty line. This option is not thread safe and MUST
2801 NOT be used with option -n<N>, where <N> >= 2.
2802 --frontend-http2-dump-response-header=<PATH>
2803 Dumps response headers sent from HTTP/2 frontend to the
2804 file denoted in <PATH>. The output is done in HTTP/1
2805 header field format and each header block is followed by
2806 an empty line. This option is not thread safe and MUST
2807 NOT be used with option -n<N>, where <N> >= 2.
2808 -o, --frontend-frame-debug
2809 Print HTTP/2 frames in frontend to stderr. This option
2810 is not thread safe and MUST NOT be used with option
2815 Run in a background. If -D is used, the current working
2816 directory is changed to '/'.
2818 Set path to save PID of this program.
2820 Run this program as <USER>. This option is intended to
2821 be used to drop root privileges.
2823 Run this program in a single process mode for debugging
2824 purpose. Without this option, nghttpx creates at least
2825 2 processes: master and worker processes. If this
2826 option is used, master and worker are unified into a
2827 single process. nghttpx still spawns additional process
2828 if neverbleed is used. In the single process mode, the
2829 signal handling feature is disabled.
2833 Set mruby script file
2834 --ignore-per-pattern-mruby-error
2835 Ignore mruby compile error for per-pattern mruby script
2836 file. If error occurred, it is treated as if no mruby
2837 file were specified for the pattern.
2841 Load configuration from <PATH>. Please note that
2842 nghttpx always tries to read the default configuration
2843 file if --conf is not given.
2845 << config->conf_path << R"(
2847 Load additional configurations from <PATH>. File <PATH>
2848 is read when configuration parser encountered this
2849 option. This option can be used multiple times, or even
2852 Print version and exit.
2853 -h, --help Print this help and exit.
2857 The <SIZE> argument is an integer and an optional unit (e.g., 10K is
2858 10 * 1024). Units are K, M and G (powers of 1024).
2860 The <DURATION> argument is an integer and an optional unit (e.g., 1s
2861 is 1 second and 500ms is 500 milliseconds). Units are h, m, s or ms
2862 (hours, minutes, seconds and milliseconds, respectively). If a unit
2863 is omitted, a second is used as unit.)"
2869 int process_options(Config *config,
2870 std::vector<std::pair<StringRef, StringRef>> &cmdcfgs) {
2871 std::array<char, STRERROR_BUFSIZE> errbuf;
2872 std::map<StringRef, size_t> pattern_addr_indexer;
2873 if (conf_exists(config->conf_path.c_str())) {
2874 LOG(NOTICE) << "Loading configuration from " << config->conf_path;
2875 std::set<StringRef> include_set;
2876 if (load_config(config, config->conf_path.c_str(), include_set,
2877 pattern_addr_indexer) == -1) {
2878 LOG(FATAL) << "Failed to load configuration from " << config->conf_path;
2881 assert(include_set.empty());
2884 // Reopen log files using configurations in file
2885 reopen_log_files(config->logging);
2888 std::set<StringRef> include_set;
2890 for (auto &p : cmdcfgs) {
2891 if (parse_config(config, p.first, p.second, include_set,
2892 pattern_addr_indexer) == -1) {
2893 LOG(FATAL) << "Failed to parse command-line argument.";
2898 assert(include_set.empty());
2901 Log::set_severity_level(config->logging.severity);
2903 auto &loggingconf = config->logging;
2905 if (loggingconf.access.syslog || loggingconf.error.syslog) {
2906 openlog("nghttpx", LOG_NDELAY | LOG_NOWAIT | LOG_PID,
2907 loggingconf.syslog_facility);
2910 if (reopen_log_files(config->logging) != 0) {
2911 LOG(FATAL) << "Failed to open log file";
2915 redirect_stderr_to_errorlog(loggingconf);
2917 if (config->uid != 0) {
2918 if (log_config()->accesslog_fd != -1 &&
2919 fchown(log_config()->accesslog_fd, config->uid, config->gid) == -1) {
2921 LOG(WARN) << "Changing owner of access log file failed: "
2922 << xsi_strerror(error, errbuf.data(), errbuf.size());
2924 if (log_config()->errorlog_fd != -1 &&
2925 fchown(log_config()->errorlog_fd, config->uid, config->gid) == -1) {
2927 LOG(WARN) << "Changing owner of error log file failed: "
2928 << xsi_strerror(error, errbuf.data(), errbuf.size());
2932 if (config->single_thread) {
2933 LOG(WARN) << "single-thread: Set workers to 1";
2934 config->num_worker = 1;
2937 auto &http2conf = config->http2;
2939 auto &dumpconf = http2conf.upstream.debug.dump;
2941 if (!dumpconf.request_header_file.empty()) {
2942 auto path = dumpconf.request_header_file.c_str();
2943 auto f = open_file_for_write(path);
2946 LOG(FATAL) << "Failed to open http2 upstream request header file: "
2951 dumpconf.request_header = f;
2953 if (config->uid != 0) {
2954 if (chown(path, config->uid, config->gid) == -1) {
2956 LOG(WARN) << "Changing owner of http2 upstream request header file "
2957 << path << " failed: "
2958 << xsi_strerror(error, errbuf.data(), errbuf.size());
2963 if (!dumpconf.response_header_file.empty()) {
2964 auto path = dumpconf.response_header_file.c_str();
2965 auto f = open_file_for_write(path);
2968 LOG(FATAL) << "Failed to open http2 upstream response header file: "
2973 dumpconf.response_header = f;
2975 if (config->uid != 0) {
2976 if (chown(path, config->uid, config->gid) == -1) {
2978 LOG(WARN) << "Changing owner of http2 upstream response header file"
2979 << " " << path << " failed: "
2980 << xsi_strerror(error, errbuf.data(), errbuf.size());
2986 auto &tlsconf = config->tls;
2988 if (tlsconf.npn_list.empty()) {
2989 tlsconf.npn_list = util::split_str(DEFAULT_NPN_LIST, ',');
2992 if (!tlsconf.tls_proto_list.empty()) {
2993 tlsconf.tls_proto_mask = tls::create_tls_proto_mask(tlsconf.tls_proto_list);
2996 // TODO We depends on the ordering of protocol version macro in
2998 if (tlsconf.min_proto_version > tlsconf.max_proto_version) {
2999 LOG(ERROR) << "tls-max-proto-version must be equal to or larger than "
3000 "tls-min-proto-version";
3004 if (tls::set_alpn_prefs(tlsconf.alpn_prefs, tlsconf.npn_list) != 0) {
3008 tlsconf.bio_method = create_bio_method();
3010 auto &listenerconf = config->conn.listener;
3011 auto &upstreamconf = config->conn.upstream;
3013 if (listenerconf.addrs.empty()) {
3014 UpstreamAddr addr{};
3015 addr.host = StringRef::from_lit("*");
3018 addr.family = AF_INET;
3019 listenerconf.addrs.push_back(addr);
3020 addr.family = AF_INET6;
3021 listenerconf.addrs.push_back(std::move(addr));
3024 if (upstreamconf.worker_connections == 0) {
3025 upstreamconf.worker_connections = std::numeric_limits<size_t>::max();
3028 if (tls::upstream_tls_enabled(config->conn) &&
3029 (tlsconf.private_key_file.empty() || tlsconf.cert_file.empty())) {
3030 LOG(FATAL) << "TLS private key and certificate files are required. "
3031 "Specify them in command-line, or in configuration file "
3032 "using private-key-file and certificate-file options.";
3036 if (tls::upstream_tls_enabled(config->conn) && !tlsconf.ocsp.disabled) {
3038 if (stat(tlsconf.ocsp.fetch_ocsp_response_file.c_str(), &buf) != 0) {
3039 tlsconf.ocsp.disabled = true;
3040 LOG(WARN) << "--fetch-ocsp-response-file: "
3041 << tlsconf.ocsp.fetch_ocsp_response_file
3042 << " not found. OCSP stapling has been disabled.";
3046 if (configure_downstream_group(config, config->http2_proxy, false, tlsconf) !=
3051 auto &proxy = config->downstream_http_proxy;
3052 if (!proxy.host.empty()) {
3053 auto hostport = util::make_hostport(StringRef{proxy.host}, proxy.port);
3054 if (resolve_hostname(&proxy.addr, proxy.host.c_str(), proxy.port,
3056 LOG(FATAL) << "Resolving backend HTTP proxy address failed: " << hostport;
3059 LOG(NOTICE) << "Backend HTTP proxy address: " << hostport << " -> "
3060 << util::to_numeric_addr(&proxy.addr);
3064 auto &memcachedconf = tlsconf.session_cache.memcached;
3065 if (!memcachedconf.host.empty()) {
3066 auto hostport = util::make_hostport(StringRef{memcachedconf.host},
3067 memcachedconf.port);
3068 if (resolve_hostname(&memcachedconf.addr, memcachedconf.host.c_str(),
3069 memcachedconf.port, memcachedconf.family) == -1) {
3071 << "Resolving memcached address for TLS session cache failed: "
3075 LOG(NOTICE) << "Memcached address for TLS session cache: " << hostport
3076 << " -> " << util::to_numeric_addr(&memcachedconf.addr);
3077 if (memcachedconf.tls) {
3078 LOG(NOTICE) << "Connection to memcached for TLS session cache will be "
3085 auto &memcachedconf = tlsconf.ticket.memcached;
3086 if (!memcachedconf.host.empty()) {
3087 auto hostport = util::make_hostport(StringRef{memcachedconf.host},
3088 memcachedconf.port);
3089 if (resolve_hostname(&memcachedconf.addr, memcachedconf.host.c_str(),
3090 memcachedconf.port, memcachedconf.family) == -1) {
3091 LOG(FATAL) << "Resolving memcached address for TLS ticket key failed: "
3095 LOG(NOTICE) << "Memcached address for TLS ticket key: " << hostport
3096 << " -> " << util::to_numeric_addr(&memcachedconf.addr);
3097 if (memcachedconf.tls) {
3098 LOG(NOTICE) << "Connection to memcached for TLS ticket key will be "
3104 if (config->rlimit_nofile) {
3105 struct rlimit lim = {static_cast<rlim_t>(config->rlimit_nofile),
3106 static_cast<rlim_t>(config->rlimit_nofile)};
3107 if (setrlimit(RLIMIT_NOFILE, &lim) != 0) {
3109 LOG(WARN) << "Setting rlimit-nofile failed: "
3110 << xsi_strerror(error, errbuf.data(), errbuf.size());
3114 auto &fwdconf = config->http.forwarded;
3116 if (fwdconf.by_node_type == ForwardedNode::OBFUSCATED &&
3117 fwdconf.by_obfuscated.empty()) {
3118 // 2 for '_' and terminal NULL
3119 auto iov = make_byte_ref(config->balloc, SHRPX_OBFUSCATED_NODE_LENGTH + 2);
3122 auto gen = util::make_mt19937();
3123 p = util::random_alpha_digit(p, p + SHRPX_OBFUSCATED_NODE_LENGTH, gen);
3125 fwdconf.by_obfuscated = StringRef{iov.base, p};
3128 if (config->http2.upstream.debug.frame_debug) {
3129 // To make it sync to logging
3131 if (isatty(fileno(stdout))) {
3132 set_color_output(true);
3137 config->http2.upstream.callbacks = create_http2_upstream_callbacks();
3138 config->http2.downstream.callbacks = create_http2_downstream_callbacks();
3145 // Closes file descriptor which are opened for listeners in config,
3146 // and are not inherited from |iaddrs|.
3147 void close_not_inherited_fd(Config *config,
3148 const std::vector<InheritedAddr> &iaddrs) {
3149 auto &listenerconf = config->conn.listener;
3151 for (auto &addr : listenerconf.addrs) {
3152 auto inherited = std::find_if(
3153 std::begin(iaddrs), std::end(iaddrs),
3154 [&addr](const InheritedAddr &iaddr) { return addr.fd == iaddr.fd; });
3156 if (inherited != std::end(iaddrs)) {
3166 void reload_config(WorkerProcess *wp) {
3169 LOG(NOTICE) << "Reloading configuration";
3171 auto cur_config = mod_config();
3172 auto new_config = std::make_unique<Config>();
3174 fill_default_config(new_config.get());
3176 new_config->conf_path =
3177 make_string_ref(new_config->balloc, cur_config->conf_path);
3178 // daemon option is ignored here.
3179 new_config->daemon = cur_config->daemon;
3180 // loop is reused, and ev_loop_flags gets ignored
3181 new_config->ev_loop_flags = cur_config->ev_loop_flags;
3182 new_config->config_revision = cur_config->config_revision + 1;
3184 rv = process_options(new_config.get(), suconfig.cmdcfgs);
3186 LOG(ERROR) << "Failed to process new configuration";
3190 auto iaddrs = get_inherited_addr_from_config(new_config->balloc, cur_config);
3192 if (create_acceptor_socket(new_config.get(), iaddrs) != 0) {
3193 close_not_inherited_fd(new_config.get(), iaddrs);
3197 // According to libev documentation, flags are ignored since we have
3198 // already created first default loop.
3199 auto loop = ev_default_loop(new_config->ev_loop_flags);
3203 // fork_worker_process and forked child process assumes new
3204 // configuration can be obtained from get_config().
3206 auto old_config = replace_config(std::move(new_config));
3208 auto pid = fork_worker_process(ipc_fd, iaddrs);
3211 LOG(ERROR) << "Failed to process new configuration";
3213 new_config = replace_config(std::move(old_config));
3214 close_not_inherited_fd(new_config.get(), iaddrs);
3219 close_unused_inherited_addr(iaddrs);
3221 // Send last worker process a graceful shutdown notice
3222 auto &last_wp = worker_processes.back();
3223 ipc_send(last_wp.get(), SHRPX_IPC_GRACEFUL_SHUTDOWN);
3224 // We no longer use signals for this worker.
3225 last_wp->shutdown_signal_watchers();
3227 worker_process_add(std::make_unique<WorkerProcess>(loop, pid, ipc_fd));
3229 if (!get_config()->pid_file.empty()) {
3235 int main(int argc, char **argv) {
3237 std::array<char, STRERROR_BUFSIZE> errbuf;
3239 nghttp2::tls::libssl_init();
3242 nghttp2::tls::LibsslGlobalLock lock;
3245 Log::set_severity_level(NOTICE);
3247 fill_default_config(mod_config());
3249 // make copy of stderr
3250 store_original_fds();
3252 // First open log files with default configuration, so that we can
3253 // log errors/warnings while reading configuration files.
3254 reopen_log_files(get_config()->logging);
3256 suconfig.original_argv = argv;
3258 // We have to copy argv, since getopt_long may change its content.
3259 suconfig.argc = argc;
3260 suconfig.argv = new char *[argc];
3262 for (int i = 0; i < argc; ++i) {
3263 suconfig.argv[i] = strdup(argv[i]);
3264 if (suconfig.argv[i] == nullptr) {
3266 LOG(FATAL) << "failed to copy argv: "
3267 << xsi_strerror(error, errbuf.data(), errbuf.size());
3272 suconfig.cwd = getcwd(nullptr, 0);
3273 if (suconfig.cwd == nullptr) {
3275 LOG(FATAL) << "failed to get current working directory: errno=" << error;
3279 auto &cmdcfgs = suconfig.cmdcfgs;
3282 static int flag = 0;
3283 static constexpr option long_options[] = {
3284 {SHRPX_OPT_DAEMON.c_str(), no_argument, nullptr, 'D'},
3285 {SHRPX_OPT_LOG_LEVEL.c_str(), required_argument, nullptr, 'L'},
3286 {SHRPX_OPT_BACKEND.c_str(), required_argument, nullptr, 'b'},
3287 {SHRPX_OPT_HTTP2_MAX_CONCURRENT_STREAMS.c_str(), required_argument,
3289 {SHRPX_OPT_FRONTEND.c_str(), required_argument, nullptr, 'f'},
3290 {"help", no_argument, nullptr, 'h'},
3291 {SHRPX_OPT_INSECURE.c_str(), no_argument, nullptr, 'k'},
3292 {SHRPX_OPT_WORKERS.c_str(), required_argument, nullptr, 'n'},
3293 {SHRPX_OPT_CLIENT_PROXY.c_str(), no_argument, nullptr, 'p'},
3294 {SHRPX_OPT_HTTP2_PROXY.c_str(), no_argument, nullptr, 's'},
3295 {"version", no_argument, nullptr, 'v'},
3296 {SHRPX_OPT_FRONTEND_FRAME_DEBUG.c_str(), no_argument, nullptr, 'o'},
3297 {SHRPX_OPT_ADD_X_FORWARDED_FOR.c_str(), no_argument, &flag, 1},
3298 {SHRPX_OPT_FRONTEND_HTTP2_READ_TIMEOUT.c_str(), required_argument,
3300 {SHRPX_OPT_FRONTEND_READ_TIMEOUT.c_str(), required_argument, &flag, 3},
3301 {SHRPX_OPT_FRONTEND_WRITE_TIMEOUT.c_str(), required_argument, &flag, 4},
3302 {SHRPX_OPT_BACKEND_READ_TIMEOUT.c_str(), required_argument, &flag, 5},
3303 {SHRPX_OPT_BACKEND_WRITE_TIMEOUT.c_str(), required_argument, &flag, 6},
3304 {SHRPX_OPT_ACCESSLOG_FILE.c_str(), required_argument, &flag, 7},
3305 {SHRPX_OPT_BACKEND_KEEP_ALIVE_TIMEOUT.c_str(), required_argument, &flag,
3307 {SHRPX_OPT_FRONTEND_HTTP2_WINDOW_BITS.c_str(), required_argument, &flag,
3309 {SHRPX_OPT_PID_FILE.c_str(), required_argument, &flag, 10},
3310 {SHRPX_OPT_USER.c_str(), required_argument, &flag, 11},
3311 {"conf", required_argument, &flag, 12},
3312 {SHRPX_OPT_SYSLOG_FACILITY.c_str(), required_argument, &flag, 14},
3313 {SHRPX_OPT_BACKLOG.c_str(), required_argument, &flag, 15},
3314 {SHRPX_OPT_CIPHERS.c_str(), required_argument, &flag, 16},
3315 {SHRPX_OPT_CLIENT.c_str(), no_argument, &flag, 17},
3316 {SHRPX_OPT_BACKEND_HTTP2_WINDOW_BITS.c_str(), required_argument, &flag,
3318 {SHRPX_OPT_CACERT.c_str(), required_argument, &flag, 19},
3319 {SHRPX_OPT_BACKEND_IPV4.c_str(), no_argument, &flag, 20},
3320 {SHRPX_OPT_BACKEND_IPV6.c_str(), no_argument, &flag, 21},
3321 {SHRPX_OPT_PRIVATE_KEY_PASSWD_FILE.c_str(), required_argument, &flag,
3323 {SHRPX_OPT_NO_VIA.c_str(), no_argument, &flag, 23},
3324 {SHRPX_OPT_SUBCERT.c_str(), required_argument, &flag, 24},
3325 {SHRPX_OPT_HTTP2_BRIDGE.c_str(), no_argument, &flag, 25},
3326 {SHRPX_OPT_BACKEND_HTTP_PROXY_URI.c_str(), required_argument, &flag,
3328 {SHRPX_OPT_BACKEND_NO_TLS.c_str(), no_argument, &flag, 27},
3329 {SHRPX_OPT_OCSP_STARTUP.c_str(), no_argument, &flag, 28},
3330 {SHRPX_OPT_FRONTEND_NO_TLS.c_str(), no_argument, &flag, 29},
3331 {SHRPX_OPT_NO_VERIFY_OCSP.c_str(), no_argument, &flag, 30},
3332 {SHRPX_OPT_BACKEND_TLS_SNI_FIELD.c_str(), required_argument, &flag, 31},
3333 {SHRPX_OPT_DH_PARAM_FILE.c_str(), required_argument, &flag, 33},
3334 {SHRPX_OPT_READ_RATE.c_str(), required_argument, &flag, 34},
3335 {SHRPX_OPT_READ_BURST.c_str(), required_argument, &flag, 35},
3336 {SHRPX_OPT_WRITE_RATE.c_str(), required_argument, &flag, 36},
3337 {SHRPX_OPT_WRITE_BURST.c_str(), required_argument, &flag, 37},
3338 {SHRPX_OPT_NPN_LIST.c_str(), required_argument, &flag, 38},
3339 {SHRPX_OPT_VERIFY_CLIENT.c_str(), no_argument, &flag, 39},
3340 {SHRPX_OPT_VERIFY_CLIENT_CACERT.c_str(), required_argument, &flag, 40},
3341 {SHRPX_OPT_CLIENT_PRIVATE_KEY_FILE.c_str(), required_argument, &flag,
3343 {SHRPX_OPT_CLIENT_CERT_FILE.c_str(), required_argument, &flag, 42},
3344 {SHRPX_OPT_FRONTEND_HTTP2_DUMP_REQUEST_HEADER.c_str(),
3345 required_argument, &flag, 43},
3346 {SHRPX_OPT_FRONTEND_HTTP2_DUMP_RESPONSE_HEADER.c_str(),
3347 required_argument, &flag, 44},
3348 {SHRPX_OPT_HTTP2_NO_COOKIE_CRUMBLING.c_str(), no_argument, &flag, 45},
3349 {SHRPX_OPT_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS.c_str(),
3350 required_argument, &flag, 46},
3351 {SHRPX_OPT_BACKEND_HTTP2_CONNECTION_WINDOW_BITS.c_str(),
3352 required_argument, &flag, 47},
3353 {SHRPX_OPT_TLS_PROTO_LIST.c_str(), required_argument, &flag, 48},
3354 {SHRPX_OPT_PADDING.c_str(), required_argument, &flag, 49},
3355 {SHRPX_OPT_WORKER_READ_RATE.c_str(), required_argument, &flag, 50},
3356 {SHRPX_OPT_WORKER_READ_BURST.c_str(), required_argument, &flag, 51},
3357 {SHRPX_OPT_WORKER_WRITE_RATE.c_str(), required_argument, &flag, 52},
3358 {SHRPX_OPT_WORKER_WRITE_BURST.c_str(), required_argument, &flag, 53},
3359 {SHRPX_OPT_ALTSVC.c_str(), required_argument, &flag, 54},
3360 {SHRPX_OPT_ADD_RESPONSE_HEADER.c_str(), required_argument, &flag, 55},
3361 {SHRPX_OPT_WORKER_FRONTEND_CONNECTIONS.c_str(), required_argument,
3363 {SHRPX_OPT_ACCESSLOG_SYSLOG.c_str(), no_argument, &flag, 57},
3364 {SHRPX_OPT_ERRORLOG_FILE.c_str(), required_argument, &flag, 58},
3365 {SHRPX_OPT_ERRORLOG_SYSLOG.c_str(), no_argument, &flag, 59},
3366 {SHRPX_OPT_STREAM_READ_TIMEOUT.c_str(), required_argument, &flag, 60},
3367 {SHRPX_OPT_STREAM_WRITE_TIMEOUT.c_str(), required_argument, &flag, 61},
3368 {SHRPX_OPT_NO_LOCATION_REWRITE.c_str(), no_argument, &flag, 62},
3369 {SHRPX_OPT_BACKEND_HTTP1_CONNECTIONS_PER_HOST.c_str(),
3370 required_argument, &flag, 63},
3371 {SHRPX_OPT_LISTENER_DISABLE_TIMEOUT.c_str(), required_argument, &flag,
3373 {SHRPX_OPT_STRIP_INCOMING_X_FORWARDED_FOR.c_str(), no_argument, &flag,
3375 {SHRPX_OPT_ACCESSLOG_FORMAT.c_str(), required_argument, &flag, 66},
3376 {SHRPX_OPT_BACKEND_HTTP1_CONNECTIONS_PER_FRONTEND.c_str(),
3377 required_argument, &flag, 67},
3378 {SHRPX_OPT_TLS_TICKET_KEY_FILE.c_str(), required_argument, &flag, 68},
3379 {SHRPX_OPT_RLIMIT_NOFILE.c_str(), required_argument, &flag, 69},
3380 {SHRPX_OPT_BACKEND_RESPONSE_BUFFER.c_str(), required_argument, &flag,
3382 {SHRPX_OPT_BACKEND_REQUEST_BUFFER.c_str(), required_argument, &flag,
3384 {SHRPX_OPT_NO_HOST_REWRITE.c_str(), no_argument, &flag, 73},
3385 {SHRPX_OPT_NO_SERVER_PUSH.c_str(), no_argument, &flag, 74},
3386 {SHRPX_OPT_BACKEND_HTTP2_CONNECTIONS_PER_WORKER.c_str(),
3387 required_argument, &flag, 76},
3388 {SHRPX_OPT_FETCH_OCSP_RESPONSE_FILE.c_str(), required_argument, &flag,
3390 {SHRPX_OPT_OCSP_UPDATE_INTERVAL.c_str(), required_argument, &flag, 78},
3391 {SHRPX_OPT_NO_OCSP.c_str(), no_argument, &flag, 79},
3392 {SHRPX_OPT_HEADER_FIELD_BUFFER.c_str(), required_argument, &flag, 80},
3393 {SHRPX_OPT_MAX_HEADER_FIELDS.c_str(), required_argument, &flag, 81},
3394 {SHRPX_OPT_ADD_REQUEST_HEADER.c_str(), required_argument, &flag, 82},
3395 {SHRPX_OPT_INCLUDE.c_str(), required_argument, &flag, 83},
3396 {SHRPX_OPT_TLS_TICKET_KEY_CIPHER.c_str(), required_argument, &flag, 84},
3397 {SHRPX_OPT_HOST_REWRITE.c_str(), no_argument, &flag, 85},
3398 {SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED.c_str(), required_argument,
3400 {SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED.c_str(), required_argument, &flag,
3402 {SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_INTERVAL.c_str(), required_argument,
3404 {SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_MAX_RETRY.c_str(),
3405 required_argument, &flag, 89},
3406 {SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_MAX_FAIL.c_str(), required_argument,
3408 {SHRPX_OPT_MRUBY_FILE.c_str(), required_argument, &flag, 91},
3409 {SHRPX_OPT_ACCEPT_PROXY_PROTOCOL.c_str(), no_argument, &flag, 93},
3410 {SHRPX_OPT_FASTOPEN.c_str(), required_argument, &flag, 94},
3411 {SHRPX_OPT_TLS_DYN_REC_WARMUP_THRESHOLD.c_str(), required_argument,
3413 {SHRPX_OPT_TLS_DYN_REC_IDLE_TIMEOUT.c_str(), required_argument, &flag,
3415 {SHRPX_OPT_ADD_FORWARDED.c_str(), required_argument, &flag, 97},
3416 {SHRPX_OPT_STRIP_INCOMING_FORWARDED.c_str(), no_argument, &flag, 98},
3417 {SHRPX_OPT_FORWARDED_BY.c_str(), required_argument, &flag, 99},
3418 {SHRPX_OPT_FORWARDED_FOR.c_str(), required_argument, &flag, 100},
3419 {SHRPX_OPT_RESPONSE_HEADER_FIELD_BUFFER.c_str(), required_argument,
3421 {SHRPX_OPT_MAX_RESPONSE_HEADER_FIELDS.c_str(), required_argument, &flag,
3423 {SHRPX_OPT_NO_HTTP2_CIPHER_BLACK_LIST.c_str(), no_argument, &flag, 103},
3424 {SHRPX_OPT_REQUEST_HEADER_FIELD_BUFFER.c_str(), required_argument,
3426 {SHRPX_OPT_MAX_REQUEST_HEADER_FIELDS.c_str(), required_argument, &flag,
3428 {SHRPX_OPT_BACKEND_HTTP1_TLS.c_str(), no_argument, &flag, 106},
3429 {SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_TLS.c_str(), no_argument, &flag,
3431 {SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_CERT_FILE.c_str(),
3432 required_argument, &flag, 109},
3433 {SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_PRIVATE_KEY_FILE.c_str(),
3434 required_argument, &flag, 110},
3435 {SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_TLS.c_str(), no_argument, &flag,
3437 {SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_CERT_FILE.c_str(),
3438 required_argument, &flag, 112},
3439 {SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_PRIVATE_KEY_FILE.c_str(),
3440 required_argument, &flag, 113},
3441 {SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_ADDRESS_FAMILY.c_str(),
3442 required_argument, &flag, 114},
3443 {SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_ADDRESS_FAMILY.c_str(),
3444 required_argument, &flag, 115},
3445 {SHRPX_OPT_BACKEND_ADDRESS_FAMILY.c_str(), required_argument, &flag,
3447 {SHRPX_OPT_FRONTEND_HTTP2_MAX_CONCURRENT_STREAMS.c_str(),
3448 required_argument, &flag, 117},
3449 {SHRPX_OPT_BACKEND_HTTP2_MAX_CONCURRENT_STREAMS.c_str(),
3450 required_argument, &flag, 118},
3451 {SHRPX_OPT_BACKEND_CONNECTIONS_PER_FRONTEND.c_str(), required_argument,
3453 {SHRPX_OPT_BACKEND_TLS.c_str(), no_argument, &flag, 120},
3454 {SHRPX_OPT_BACKEND_CONNECTIONS_PER_HOST.c_str(), required_argument,
3456 {SHRPX_OPT_ERROR_PAGE.c_str(), required_argument, &flag, 122},
3457 {SHRPX_OPT_NO_KQUEUE.c_str(), no_argument, &flag, 123},
3458 {SHRPX_OPT_FRONTEND_HTTP2_SETTINGS_TIMEOUT.c_str(), required_argument,
3460 {SHRPX_OPT_BACKEND_HTTP2_SETTINGS_TIMEOUT.c_str(), required_argument,
3462 {SHRPX_OPT_API_MAX_REQUEST_BODY.c_str(), required_argument, &flag, 126},
3463 {SHRPX_OPT_BACKEND_MAX_BACKOFF.c_str(), required_argument, &flag, 127},
3464 {SHRPX_OPT_SERVER_NAME.c_str(), required_argument, &flag, 128},
3465 {SHRPX_OPT_NO_SERVER_REWRITE.c_str(), no_argument, &flag, 129},
3466 {SHRPX_OPT_FRONTEND_HTTP2_OPTIMIZE_WRITE_BUFFER_SIZE.c_str(),
3467 no_argument, &flag, 130},
3468 {SHRPX_OPT_FRONTEND_HTTP2_OPTIMIZE_WINDOW_SIZE.c_str(), no_argument,
3470 {SHRPX_OPT_FRONTEND_HTTP2_WINDOW_SIZE.c_str(), required_argument, &flag,
3472 {SHRPX_OPT_FRONTEND_HTTP2_CONNECTION_WINDOW_SIZE.c_str(),
3473 required_argument, &flag, 133},
3474 {SHRPX_OPT_BACKEND_HTTP2_WINDOW_SIZE.c_str(), required_argument, &flag,
3476 {SHRPX_OPT_BACKEND_HTTP2_CONNECTION_WINDOW_SIZE.c_str(),
3477 required_argument, &flag, 135},
3478 {SHRPX_OPT_FRONTEND_HTTP2_ENCODER_DYNAMIC_TABLE_SIZE.c_str(),
3479 required_argument, &flag, 136},
3480 {SHRPX_OPT_FRONTEND_HTTP2_DECODER_DYNAMIC_TABLE_SIZE.c_str(),
3481 required_argument, &flag, 137},
3482 {SHRPX_OPT_BACKEND_HTTP2_ENCODER_DYNAMIC_TABLE_SIZE.c_str(),
3483 required_argument, &flag, 138},
3484 {SHRPX_OPT_BACKEND_HTTP2_DECODER_DYNAMIC_TABLE_SIZE.c_str(),
3485 required_argument, &flag, 139},
3486 {SHRPX_OPT_ECDH_CURVES.c_str(), required_argument, &flag, 140},
3487 {SHRPX_OPT_TLS_SCT_DIR.c_str(), required_argument, &flag, 141},
3488 {SHRPX_OPT_BACKEND_CONNECT_TIMEOUT.c_str(), required_argument, &flag,
3490 {SHRPX_OPT_DNS_CACHE_TIMEOUT.c_str(), required_argument, &flag, 143},
3491 {SHRPX_OPT_DNS_LOOKUP_TIMEOUT.c_str(), required_argument, &flag, 144},
3492 {SHRPX_OPT_DNS_MAX_TRY.c_str(), required_argument, &flag, 145},
3493 {SHRPX_OPT_FRONTEND_KEEP_ALIVE_TIMEOUT.c_str(), required_argument,
3495 {SHRPX_OPT_PSK_SECRETS.c_str(), required_argument, &flag, 147},
3496 {SHRPX_OPT_CLIENT_PSK_SECRETS.c_str(), required_argument, &flag, 148},
3497 {SHRPX_OPT_CLIENT_NO_HTTP2_CIPHER_BLACK_LIST.c_str(), no_argument,
3499 {SHRPX_OPT_CLIENT_CIPHERS.c_str(), required_argument, &flag, 150},
3500 {SHRPX_OPT_ACCESSLOG_WRITE_EARLY.c_str(), no_argument, &flag, 151},
3501 {SHRPX_OPT_TLS_MIN_PROTO_VERSION.c_str(), required_argument, &flag,
3503 {SHRPX_OPT_TLS_MAX_PROTO_VERSION.c_str(), required_argument, &flag,
3505 {SHRPX_OPT_REDIRECT_HTTPS_PORT.c_str(), required_argument, &flag, 154},
3506 {SHRPX_OPT_FRONTEND_MAX_REQUESTS.c_str(), required_argument, &flag,
3508 {SHRPX_OPT_SINGLE_THREAD.c_str(), no_argument, &flag, 156},
3509 {SHRPX_OPT_NO_ADD_X_FORWARDED_PROTO.c_str(), no_argument, &flag, 157},
3510 {SHRPX_OPT_NO_STRIP_INCOMING_X_FORWARDED_PROTO.c_str(), no_argument,
3512 {SHRPX_OPT_SINGLE_PROCESS.c_str(), no_argument, &flag, 159},
3513 {SHRPX_OPT_VERIFY_CLIENT_TOLERATE_EXPIRED.c_str(), no_argument, &flag,
3515 {SHRPX_OPT_IGNORE_PER_PATTERN_MRUBY_ERROR.c_str(), no_argument, &flag,
3517 {SHRPX_OPT_TLS_NO_POSTPONE_EARLY_DATA.c_str(), no_argument, &flag, 162},
3518 {SHRPX_OPT_TLS_MAX_EARLY_DATA.c_str(), required_argument, &flag, 163},
3519 {SHRPX_OPT_TLS13_CIPHERS.c_str(), required_argument, &flag, 164},
3520 {SHRPX_OPT_TLS13_CLIENT_CIPHERS.c_str(), required_argument, &flag, 165},
3521 {SHRPX_OPT_NO_STRIP_INCOMING_EARLY_DATA.c_str(), no_argument, &flag,
3523 {nullptr, 0, nullptr, 0}};
3525 int option_index = 0;
3526 int c = getopt_long(argc, argv, "DL:b:c:f:hkn:opsv", long_options,
3533 cmdcfgs.emplace_back(SHRPX_OPT_DAEMON, StringRef::from_lit("yes"));
3536 cmdcfgs.emplace_back(SHRPX_OPT_LOG_LEVEL, StringRef{optarg});
3539 cmdcfgs.emplace_back(SHRPX_OPT_BACKEND, StringRef{optarg});
3542 cmdcfgs.emplace_back(SHRPX_OPT_HTTP2_MAX_CONCURRENT_STREAMS,
3546 cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND, StringRef{optarg});
3549 print_help(std::cout);
3552 cmdcfgs.emplace_back(SHRPX_OPT_INSECURE, StringRef::from_lit("yes"));
3555 cmdcfgs.emplace_back(SHRPX_OPT_WORKERS, StringRef{optarg});
3558 cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_FRAME_DEBUG,
3559 StringRef::from_lit("yes"));
3562 cmdcfgs.emplace_back(SHRPX_OPT_CLIENT_PROXY, StringRef::from_lit("yes"));
3565 cmdcfgs.emplace_back(SHRPX_OPT_HTTP2_PROXY, StringRef::from_lit("yes"));
3568 print_version(std::cout);
3571 util::show_candidates(argv[optind - 1], long_options);
3576 // --add-x-forwarded-for
3577 cmdcfgs.emplace_back(SHRPX_OPT_ADD_X_FORWARDED_FOR,
3578 StringRef::from_lit("yes"));
3581 // --frontend-http2-read-timeout
3582 cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_HTTP2_READ_TIMEOUT,
3586 // --frontend-read-timeout
3587 cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_READ_TIMEOUT,
3591 // --frontend-write-timeout
3592 cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_WRITE_TIMEOUT,
3596 // --backend-read-timeout
3597 cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_READ_TIMEOUT, StringRef{optarg});
3600 // --backend-write-timeout
3601 cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_WRITE_TIMEOUT,
3605 cmdcfgs.emplace_back(SHRPX_OPT_ACCESSLOG_FILE, StringRef{optarg});
3608 // --backend-keep-alive-timeout
3609 cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_KEEP_ALIVE_TIMEOUT,
3613 // --frontend-http2-window-bits
3614 cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_HTTP2_WINDOW_BITS,
3618 cmdcfgs.emplace_back(SHRPX_OPT_PID_FILE, StringRef{optarg});
3621 cmdcfgs.emplace_back(SHRPX_OPT_USER, StringRef{optarg});
3625 mod_config()->conf_path =
3626 make_string_ref(mod_config()->balloc, StringRef{optarg});
3629 // --syslog-facility
3630 cmdcfgs.emplace_back(SHRPX_OPT_SYSLOG_FACILITY, StringRef{optarg});
3634 cmdcfgs.emplace_back(SHRPX_OPT_BACKLOG, StringRef{optarg});
3638 cmdcfgs.emplace_back(SHRPX_OPT_CIPHERS, StringRef{optarg});
3642 cmdcfgs.emplace_back(SHRPX_OPT_CLIENT, StringRef::from_lit("yes"));
3645 // --backend-http2-window-bits
3646 cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP2_WINDOW_BITS,
3651 cmdcfgs.emplace_back(SHRPX_OPT_CACERT, StringRef{optarg});
3655 cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_IPV4,
3656 StringRef::from_lit("yes"));
3660 cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_IPV6,
3661 StringRef::from_lit("yes"));
3664 // --private-key-passwd-file
3665 cmdcfgs.emplace_back(SHRPX_OPT_PRIVATE_KEY_PASSWD_FILE,
3670 cmdcfgs.emplace_back(SHRPX_OPT_NO_VIA, StringRef::from_lit("yes"));
3674 cmdcfgs.emplace_back(SHRPX_OPT_SUBCERT, StringRef{optarg});
3678 cmdcfgs.emplace_back(SHRPX_OPT_HTTP2_BRIDGE,
3679 StringRef::from_lit("yes"));
3682 // --backend-http-proxy-uri
3683 cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP_PROXY_URI,
3688 cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_NO_TLS,
3689 StringRef::from_lit("yes"));
3693 cmdcfgs.emplace_back(SHRPX_OPT_OCSP_STARTUP,
3694 StringRef::from_lit("yes"));
3697 // --frontend-no-tls
3698 cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_NO_TLS,
3699 StringRef::from_lit("yes"));
3703 cmdcfgs.emplace_back(SHRPX_OPT_NO_VERIFY_OCSP,
3704 StringRef::from_lit("yes"));
3707 // --backend-tls-sni-field
3708 cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_TLS_SNI_FIELD,
3713 cmdcfgs.emplace_back(SHRPX_OPT_DH_PARAM_FILE, StringRef{optarg});
3717 cmdcfgs.emplace_back(SHRPX_OPT_READ_RATE, StringRef{optarg});
3721 cmdcfgs.emplace_back(SHRPX_OPT_READ_BURST, StringRef{optarg});
3725 cmdcfgs.emplace_back(SHRPX_OPT_WRITE_RATE, StringRef{optarg});
3729 cmdcfgs.emplace_back(SHRPX_OPT_WRITE_BURST, StringRef{optarg});
3733 cmdcfgs.emplace_back(SHRPX_OPT_NPN_LIST, StringRef{optarg});
3737 cmdcfgs.emplace_back(SHRPX_OPT_VERIFY_CLIENT,
3738 StringRef::from_lit("yes"));
3741 // --verify-client-cacert
3742 cmdcfgs.emplace_back(SHRPX_OPT_VERIFY_CLIENT_CACERT, StringRef{optarg});
3745 // --client-private-key-file
3746 cmdcfgs.emplace_back(SHRPX_OPT_CLIENT_PRIVATE_KEY_FILE,
3750 // --client-cert-file
3751 cmdcfgs.emplace_back(SHRPX_OPT_CLIENT_CERT_FILE, StringRef{optarg});
3754 // --frontend-http2-dump-request-header
3755 cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_HTTP2_DUMP_REQUEST_HEADER,
3759 // --frontend-http2-dump-response-header
3760 cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_HTTP2_DUMP_RESPONSE_HEADER,
3764 // --http2-no-cookie-crumbling
3765 cmdcfgs.emplace_back(SHRPX_OPT_HTTP2_NO_COOKIE_CRUMBLING,
3766 StringRef::from_lit("yes"));
3769 // --frontend-http2-connection-window-bits
3770 cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS,
3774 // --backend-http2-connection-window-bits
3775 cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP2_CONNECTION_WINDOW_BITS,
3780 cmdcfgs.emplace_back(SHRPX_OPT_TLS_PROTO_LIST, StringRef{optarg});
3784 cmdcfgs.emplace_back(SHRPX_OPT_PADDING, StringRef{optarg});
3787 // --worker-read-rate
3788 cmdcfgs.emplace_back(SHRPX_OPT_WORKER_READ_RATE, StringRef{optarg});
3791 // --worker-read-burst
3792 cmdcfgs.emplace_back(SHRPX_OPT_WORKER_READ_BURST, StringRef{optarg});
3795 // --worker-write-rate
3796 cmdcfgs.emplace_back(SHRPX_OPT_WORKER_WRITE_RATE, StringRef{optarg});
3799 // --worker-write-burst
3800 cmdcfgs.emplace_back(SHRPX_OPT_WORKER_WRITE_BURST, StringRef{optarg});
3804 cmdcfgs.emplace_back(SHRPX_OPT_ALTSVC, StringRef{optarg});
3807 // --add-response-header
3808 cmdcfgs.emplace_back(SHRPX_OPT_ADD_RESPONSE_HEADER, StringRef{optarg});
3811 // --worker-frontend-connections
3812 cmdcfgs.emplace_back(SHRPX_OPT_WORKER_FRONTEND_CONNECTIONS,
3816 // --accesslog-syslog
3817 cmdcfgs.emplace_back(SHRPX_OPT_ACCESSLOG_SYSLOG,
3818 StringRef::from_lit("yes"));
3822 cmdcfgs.emplace_back(SHRPX_OPT_ERRORLOG_FILE, StringRef{optarg});
3825 // --errorlog-syslog
3826 cmdcfgs.emplace_back(SHRPX_OPT_ERRORLOG_SYSLOG,
3827 StringRef::from_lit("yes"));
3830 // --stream-read-timeout
3831 cmdcfgs.emplace_back(SHRPX_OPT_STREAM_READ_TIMEOUT, StringRef{optarg});
3834 // --stream-write-timeout
3835 cmdcfgs.emplace_back(SHRPX_OPT_STREAM_WRITE_TIMEOUT, StringRef{optarg});
3838 // --no-location-rewrite
3839 cmdcfgs.emplace_back(SHRPX_OPT_NO_LOCATION_REWRITE,
3840 StringRef::from_lit("yes"));
3843 // --backend-http1-connections-per-host
3844 cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP1_CONNECTIONS_PER_HOST,
3848 // --listener-disable-timeout
3849 cmdcfgs.emplace_back(SHRPX_OPT_LISTENER_DISABLE_TIMEOUT,
3853 // --strip-incoming-x-forwarded-for
3854 cmdcfgs.emplace_back(SHRPX_OPT_STRIP_INCOMING_X_FORWARDED_FOR,
3855 StringRef::from_lit("yes"));
3858 // --accesslog-format
3859 cmdcfgs.emplace_back(SHRPX_OPT_ACCESSLOG_FORMAT, StringRef{optarg});
3862 // --backend-http1-connections-per-frontend
3863 cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP1_CONNECTIONS_PER_FRONTEND,
3867 // --tls-ticket-key-file
3868 cmdcfgs.emplace_back(SHRPX_OPT_TLS_TICKET_KEY_FILE, StringRef{optarg});
3872 cmdcfgs.emplace_back(SHRPX_OPT_RLIMIT_NOFILE, StringRef{optarg});
3875 // --backend-response-buffer
3876 cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_RESPONSE_BUFFER,
3880 // --backend-request-buffer
3881 cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_REQUEST_BUFFER,
3885 // --no-host-rewrite
3886 cmdcfgs.emplace_back(SHRPX_OPT_NO_HOST_REWRITE,
3887 StringRef::from_lit("yes"));
3891 cmdcfgs.emplace_back(SHRPX_OPT_NO_SERVER_PUSH,
3892 StringRef::from_lit("yes"));
3895 // --backend-http2-connections-per-worker
3896 cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP2_CONNECTIONS_PER_WORKER,
3900 // --fetch-ocsp-response-file
3901 cmdcfgs.emplace_back(SHRPX_OPT_FETCH_OCSP_RESPONSE_FILE,
3905 // --ocsp-update-interval
3906 cmdcfgs.emplace_back(SHRPX_OPT_OCSP_UPDATE_INTERVAL, StringRef{optarg});
3910 cmdcfgs.emplace_back(SHRPX_OPT_NO_OCSP, StringRef::from_lit("yes"));
3913 // --header-field-buffer
3914 cmdcfgs.emplace_back(SHRPX_OPT_HEADER_FIELD_BUFFER, StringRef{optarg});
3917 // --max-header-fields
3918 cmdcfgs.emplace_back(SHRPX_OPT_MAX_HEADER_FIELDS, StringRef{optarg});
3921 // --add-request-header
3922 cmdcfgs.emplace_back(SHRPX_OPT_ADD_REQUEST_HEADER, StringRef{optarg});
3926 cmdcfgs.emplace_back(SHRPX_OPT_INCLUDE, StringRef{optarg});
3929 // --tls-ticket-key-cipher
3930 cmdcfgs.emplace_back(SHRPX_OPT_TLS_TICKET_KEY_CIPHER,
3935 cmdcfgs.emplace_back(SHRPX_OPT_HOST_REWRITE,
3936 StringRef::from_lit("yes"));
3939 // --tls-session-cache-memcached
3940 cmdcfgs.emplace_back(SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED,
3944 // --tls-ticket-key-memcached
3945 cmdcfgs.emplace_back(SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED,
3949 // --tls-ticket-key-memcached-interval
3950 cmdcfgs.emplace_back(SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_INTERVAL,
3954 // --tls-ticket-key-memcached-max-retry
3955 cmdcfgs.emplace_back(SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_MAX_RETRY,
3959 // --tls-ticket-key-memcached-max-fail
3960 cmdcfgs.emplace_back(SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_MAX_FAIL,
3965 cmdcfgs.emplace_back(SHRPX_OPT_MRUBY_FILE, StringRef{optarg});
3968 // --accept-proxy-protocol
3969 cmdcfgs.emplace_back(SHRPX_OPT_ACCEPT_PROXY_PROTOCOL,
3970 StringRef::from_lit("yes"));
3974 cmdcfgs.emplace_back(SHRPX_OPT_FASTOPEN, StringRef{optarg});
3977 // --tls-dyn-rec-warmup-threshold
3978 cmdcfgs.emplace_back(SHRPX_OPT_TLS_DYN_REC_WARMUP_THRESHOLD,
3982 // --tls-dyn-rec-idle-timeout
3983 cmdcfgs.emplace_back(SHRPX_OPT_TLS_DYN_REC_IDLE_TIMEOUT,
3988 cmdcfgs.emplace_back(SHRPX_OPT_ADD_FORWARDED, StringRef{optarg});
3991 // --strip-incoming-forwarded
3992 cmdcfgs.emplace_back(SHRPX_OPT_STRIP_INCOMING_FORWARDED,
3993 StringRef::from_lit("yes"));
3997 cmdcfgs.emplace_back(SHRPX_OPT_FORWARDED_BY, StringRef{optarg});
4001 cmdcfgs.emplace_back(SHRPX_OPT_FORWARDED_FOR, StringRef{optarg});
4004 // --response-header-field-buffer
4005 cmdcfgs.emplace_back(SHRPX_OPT_RESPONSE_HEADER_FIELD_BUFFER,
4009 // --max-response-header-fields
4010 cmdcfgs.emplace_back(SHRPX_OPT_MAX_RESPONSE_HEADER_FIELDS,
4014 // --no-http2-cipher-black-list
4015 cmdcfgs.emplace_back(SHRPX_OPT_NO_HTTP2_CIPHER_BLACK_LIST,
4016 StringRef::from_lit("yes"));
4019 // --request-header-field-buffer
4020 cmdcfgs.emplace_back(SHRPX_OPT_REQUEST_HEADER_FIELD_BUFFER,
4024 // --max-request-header-fields
4025 cmdcfgs.emplace_back(SHRPX_OPT_MAX_REQUEST_HEADER_FIELDS,
4029 // --backend-http1-tls
4030 cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP1_TLS,
4031 StringRef::from_lit("yes"));
4034 // --tls-session-cache-memcached-tls
4035 cmdcfgs.emplace_back(SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_TLS,
4036 StringRef::from_lit("yes"));
4039 // --tls-session-cache-memcached-cert-file
4040 cmdcfgs.emplace_back(SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_CERT_FILE,
4044 // --tls-session-cache-memcached-private-key-file
4045 cmdcfgs.emplace_back(
4046 SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_PRIVATE_KEY_FILE,
4050 // --tls-ticket-key-memcached-tls
4051 cmdcfgs.emplace_back(SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_TLS,
4052 StringRef::from_lit("yes"));
4055 // --tls-ticket-key-memcached-cert-file
4056 cmdcfgs.emplace_back(SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_CERT_FILE,
4060 // --tls-ticket-key-memcached-private-key-file
4061 cmdcfgs.emplace_back(
4062 SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_PRIVATE_KEY_FILE,
4066 // --tls-ticket-key-memcached-address-family
4067 cmdcfgs.emplace_back(SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_ADDRESS_FAMILY,
4071 // --tls-session-cache-memcached-address-family
4072 cmdcfgs.emplace_back(
4073 SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_ADDRESS_FAMILY,
4077 // --backend-address-family
4078 cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_ADDRESS_FAMILY,
4082 // --frontend-http2-max-concurrent-streams
4083 cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_HTTP2_MAX_CONCURRENT_STREAMS,
4087 // --backend-http2-max-concurrent-streams
4088 cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP2_MAX_CONCURRENT_STREAMS,
4092 // --backend-connections-per-frontend
4093 cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_CONNECTIONS_PER_FRONTEND,
4098 cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_TLS, StringRef::from_lit("yes"));
4101 // --backend-connections-per-host
4102 cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_CONNECTIONS_PER_HOST,
4107 cmdcfgs.emplace_back(SHRPX_OPT_ERROR_PAGE, StringRef{optarg});
4111 cmdcfgs.emplace_back(SHRPX_OPT_NO_KQUEUE, StringRef::from_lit("yes"));
4114 // --frontend-http2-settings-timeout
4115 cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_HTTP2_SETTINGS_TIMEOUT,
4119 // --backend-http2-settings-timeout
4120 cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP2_SETTINGS_TIMEOUT,
4124 // --api-max-request-body
4125 cmdcfgs.emplace_back(SHRPX_OPT_API_MAX_REQUEST_BODY, StringRef{optarg});
4128 // --backend-max-backoff
4129 cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_MAX_BACKOFF, StringRef{optarg});
4133 cmdcfgs.emplace_back(SHRPX_OPT_SERVER_NAME, StringRef{optarg});
4136 // --no-server-rewrite
4137 cmdcfgs.emplace_back(SHRPX_OPT_NO_SERVER_REWRITE,
4138 StringRef::from_lit("yes"));
4141 // --frontend-http2-optimize-write-buffer-size
4142 cmdcfgs.emplace_back(
4143 SHRPX_OPT_FRONTEND_HTTP2_OPTIMIZE_WRITE_BUFFER_SIZE,
4144 StringRef::from_lit("yes"));
4147 // --frontend-http2-optimize-window-size
4148 cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_HTTP2_OPTIMIZE_WINDOW_SIZE,
4149 StringRef::from_lit("yes"));
4152 // --frontend-http2-window-size
4153 cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_HTTP2_WINDOW_SIZE,
4157 // --frontend-http2-connection-window-size
4158 cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_HTTP2_CONNECTION_WINDOW_SIZE,
4162 // --backend-http2-window-size
4163 cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP2_WINDOW_SIZE,
4167 // --backend-http2-connection-window-size
4168 cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP2_CONNECTION_WINDOW_SIZE,
4172 // --frontend-http2-encoder-dynamic-table-size
4173 cmdcfgs.emplace_back(
4174 SHRPX_OPT_FRONTEND_HTTP2_ENCODER_DYNAMIC_TABLE_SIZE,
4178 // --frontend-http2-decoder-dynamic-table-size
4179 cmdcfgs.emplace_back(
4180 SHRPX_OPT_FRONTEND_HTTP2_DECODER_DYNAMIC_TABLE_SIZE,
4184 // --backend-http2-encoder-dynamic-table-size
4185 cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP2_ENCODER_DYNAMIC_TABLE_SIZE,
4189 // --backend-http2-decoder-dynamic-table-size
4190 cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP2_DECODER_DYNAMIC_TABLE_SIZE,
4195 cmdcfgs.emplace_back(SHRPX_OPT_ECDH_CURVES, StringRef{optarg});
4199 cmdcfgs.emplace_back(SHRPX_OPT_TLS_SCT_DIR, StringRef{optarg});
4202 // --backend-connect-timeout
4203 cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_CONNECT_TIMEOUT,
4207 // --dns-cache-timeout
4208 cmdcfgs.emplace_back(SHRPX_OPT_DNS_CACHE_TIMEOUT, StringRef{optarg});
4211 // --dns-lookup-timeou
4212 cmdcfgs.emplace_back(SHRPX_OPT_DNS_LOOKUP_TIMEOUT, StringRef{optarg});
4216 cmdcfgs.emplace_back(SHRPX_OPT_DNS_MAX_TRY, StringRef{optarg});
4219 // --frontend-keep-alive-timeout
4220 cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_KEEP_ALIVE_TIMEOUT,
4225 cmdcfgs.emplace_back(SHRPX_OPT_PSK_SECRETS, StringRef{optarg});
4228 // --client-psk-secrets
4229 cmdcfgs.emplace_back(SHRPX_OPT_CLIENT_PSK_SECRETS, StringRef{optarg});
4232 // --client-no-http2-cipher-black-list
4233 cmdcfgs.emplace_back(SHRPX_OPT_CLIENT_NO_HTTP2_CIPHER_BLACK_LIST,
4234 StringRef::from_lit("yes"));
4238 cmdcfgs.emplace_back(SHRPX_OPT_CLIENT_CIPHERS, StringRef{optarg});
4241 // --accesslog-write-early
4242 cmdcfgs.emplace_back(SHRPX_OPT_ACCESSLOG_WRITE_EARLY,
4243 StringRef::from_lit("yes"));
4246 // --tls-min-proto-version
4247 cmdcfgs.emplace_back(SHRPX_OPT_TLS_MIN_PROTO_VERSION,
4251 // --tls-max-proto-version
4252 cmdcfgs.emplace_back(SHRPX_OPT_TLS_MAX_PROTO_VERSION,
4256 // --redirect-https-port
4257 cmdcfgs.emplace_back(SHRPX_OPT_REDIRECT_HTTPS_PORT, StringRef{optarg});
4260 // --frontend-max-requests
4261 cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_MAX_REQUESTS,
4266 cmdcfgs.emplace_back(SHRPX_OPT_SINGLE_THREAD,
4267 StringRef::from_lit("yes"));
4270 // --no-add-x-forwarded-proto
4271 cmdcfgs.emplace_back(SHRPX_OPT_NO_ADD_X_FORWARDED_PROTO,
4272 StringRef::from_lit("yes"));
4275 // --no-strip-incoming-x-forwarded-proto
4276 cmdcfgs.emplace_back(SHRPX_OPT_NO_STRIP_INCOMING_X_FORWARDED_PROTO,
4277 StringRef::from_lit("yes"));
4281 cmdcfgs.emplace_back(SHRPX_OPT_SINGLE_PROCESS,
4282 StringRef::from_lit("yes"));
4285 // --verify-client-tolerate-expired
4286 cmdcfgs.emplace_back(SHRPX_OPT_VERIFY_CLIENT_TOLERATE_EXPIRED,
4287 StringRef::from_lit("yes"));
4290 // --ignore-per-pattern-mruby-error
4291 cmdcfgs.emplace_back(SHRPX_OPT_IGNORE_PER_PATTERN_MRUBY_ERROR,
4292 StringRef::from_lit("yes"));
4295 // --tls-no-postpone-early-data
4296 cmdcfgs.emplace_back(SHRPX_OPT_TLS_NO_POSTPONE_EARLY_DATA,
4297 StringRef::from_lit("yes"));
4300 // --tls-max-early-data
4301 cmdcfgs.emplace_back(SHRPX_OPT_TLS_MAX_EARLY_DATA, StringRef{optarg});
4305 cmdcfgs.emplace_back(SHRPX_OPT_TLS13_CIPHERS, StringRef{optarg});
4308 // --tls13-client-ciphers
4309 cmdcfgs.emplace_back(SHRPX_OPT_TLS13_CLIENT_CIPHERS, StringRef{optarg});
4312 // --no-strip-incoming-early-data
4313 cmdcfgs.emplace_back(SHRPX_OPT_NO_STRIP_INCOMING_EARLY_DATA,
4314 StringRef::from_lit("yes"));
4325 if (argc - optind >= 2) {
4326 cmdcfgs.emplace_back(SHRPX_OPT_PRIVATE_KEY_FILE, StringRef{argv[optind++]});
4327 cmdcfgs.emplace_back(SHRPX_OPT_CERTIFICATE_FILE, StringRef{argv[optind++]});
4330 rv = process_options(mod_config(), cmdcfgs);
4335 if (event_loop() != 0) {
4339 LOG(NOTICE) << "Shutdown momentarily";
4341 delete_log_config();
4346 } // namespace shrpx
4348 int main(int argc, char **argv) { return run_app(shrpx::main, argc, argv); }