run_as {
  # Description of the directive
  desc "The user the app should be run as. This user should have the minimal amount of privileges necessary to successfully run the application (i.e. read-only access to the Shiny application directory). Note that this directive cannot be used with `user_apps`, as `user_apps` always run as the user who owns the application.";

  # required parameter
  param String users... "The username that should be used to run the app. If using home_dirs, this can also be the special keyword `:HOME_USER:` which will instruct `home_dirs` to run as the user in whose home directory the application exists. If using a special keyword like `:HOME_USER:`, you can specify additional usernames afterwards which will be used when this directive is applied to hosting models other than `home_dirs`.";

  # List of parent node names that are valid for this directive ($ means root)
  at $ server location;

  # Up to how many times can this directive appear within a node's scope (not
  # including descendant nodes)?
  maxcount 1;
}

socket_dir {
  desc "The path to the (empty) directory within which Shiny worker processes should create domain sockets. The directory should be owned by root with permissions set to `0333`. Defaults to `/var/shiny-server/sockets` if this directive is not present.";
  param String path "The domain socket directory path (should be absolute).";
  at $;
  undocumented;
}

access_log {
  desc "The file path of the HTTP access log.";
  param String path "The file path where the access log should be written";
  param String [format] "The log file format; see [Connect documentation](http://www.senchalabs.org/connect/logger.html) under \"Formats\"" default;
  at $;
}

server {
  desc "Declares an HTTP server. You need one of these for each port/IP address combination this Shiny Server instance should listen on.";
  at $;
}

listen {
  desc "Directs the enclosing server scope to listen on the specified port/IP address combination.";
  param Integer port "Port to listen on";
  # Optional parameter
  param String [host] "IP address to listen on (`*` or `::` for all, or `0.0.0.0` for all IPv4); hostnames are not allowed, please use raw IPv4 or IPv6 address only. IPv6 zone IDs are not supported." *;
  at server;
  maxcount 1;
}

server_name {
  desc "Directs the enclosing server scope to only honor requests that have the given host headers (i.e. virtual hosts).";
  # Variadic parameter
  param String names... "The virtual hostname(s) to bind this server to";
  at server;
  maxcount 1;
}

location {
  desc "Creates a scope that configures the given URL as a website (`site_dir`), specific application (`app_dir`), autouser root (`user_apps`), autouser root with `run_as` support (`user_dirs`), or redirect to a different URL (`redirect`).";
  param String path "The request path that this location should match";
  at server location;
}

site_dir {
  desc "Configures the enclosing location scope to be a website that can contain both Shiny applications and unrelated static assets in a single directory tree.";
  param String rootPath "The path to the root directory of the website";
  at location;
  maxcount 1;
  precludes user_apps app_dir redirect user_dirs;
}

directory_index {
  desc "When enabled, if a directory is requested by the client and an `index.html` file is not present, a list of the directory contents is created automatically and returned to the client. If this directive is not present in a custom config file, the default behavior is to disable directory indexes. However, it is enabled if no config file is present at all (in other words, the default config file has it enabled).";
  param Boolean enabled "Whether directory contents should automatically displayed";
  at $ server location;
  maxcount 1;
}

user_apps {
  desc "DEPRECATED! This directive has been deprecated in favor of `user_dirs`, which offers more flexibility with regards to the `run_as` configuration. Configures the enclosing location scope to be an autouser root, meaning that applications will be served up from users' ~/ShinyApps directories and all Shiny processes will run as the user in whose directory the application is found.";
  param Boolean [enabled] "Whether this location should serve up all users' ~/ShinyApps directories" on;
  at location;
  maxcount 1;
  precludes app_dir redirect log_dir run_as user_dirs site_dir;
}

user_dirs {
  desc "Configures the enclosing location scope to be an autouser root, meaning that applications will be served up from users' ~/ShinyApps directories. This directive does respect an affiliated run_as setting, meaning that the applications will be executed as whichever user is configured in the applicable run_as setting. Note that many distributions, by default, will prohibit users from being able to access each other's home directories.";
  param Boolean [enabled] "Whether this location should serve up all users' ~/ShinyApps directories" on;
  at location;
  maxcount 1;
  precludes app_dir redirect log_dir site_dir user_apps;
}

app_dir {
  desc "Configures the enclosing location scope to serve up the specified Shiny application.";
  param String path "The path to the Shiny application directory";
  at location;
  maxcount 1;
  precludes redirect user_apps site_dir user_dirs;
}

redirect {
  desc "Configures the enclosing location to redirect all requests to the specified URL.";
  param String url "The URL (or base URL) to redirect to";
  param Integer [statusCode] "The status code to send with the response (usually 301 for permanent redirects or 302 for temporary redirects)" 302;
  param Boolean [exact] "Whether to match on the URL exactly; if false, any subpaths will match as well" true;

  at location;
  maxcount 1;

  precludes log_dir google_analytics_id;
}

log_dir {
  desc "Directs the application to write error logs to the specified directory. Only applies to location scopes that are configured with `app_dir` or `site_dir`, as `user_apps` (autouser) always writes error logs to `~/ShinyApps/log`. In addition, starting in v1.5.13 you can set the environment variable `SHINY_LOG_STDERR` to any non-empty value to instruct Shiny Server to emit stderr output from Shiny apps to the main process's own stderr.";
  param String path "The path to which application log files should be written";
  at $ server location;
  maxcount 1;
}

log_file_mode {
  desc "Specifies the file permissions to use for newly created application log files. Since Shiny Server v1.5.8, umask will be ignored; the mode will be applied via chmod.";
  param String [mode] "The file mode to use, interpreted as an octal number. Set this to `0644` to allow all users on the system to read log files." 0640;
  at $ server location;
  maxcount 1;
}

members_of {
  desc "Restricts a `user_apps` or `user_dirs` (autouser) scope to require membership in one or more groups (or, if no arguments are passed, lifts group restrictions from a `members_of` directive in a parent scope).";
  param String groups... "Users must be a member of at least one of these groups in order to deploy applications; if no groups are provided, then all users are allowed";
  at $ server location;
  maxcount 1;
}

google_analytics_id {
  desc "Configure Google Analytics tracking code to be inserted in Shiny application pages.";
  param String gaid "The Google tracking ID, for example, UA-18988-1";
  at $ server location;
  internal true;  # Probably shouldn't document this since it will change soon
}

app_init_timeout {
  desc "Defines the amount of time Shiny Server will wait for an R process to start before giving up.";
  param Integer timeout "The number of seconds to wait for the application to start.";
  at $ server location application;
  maxcount 1;
}

app_idle_timeout {
  desc "Defines the amount of time an R process will persist with no connections before being terminated. Defaults to 5 seconds. Set to 0 to disable.";
  param Integer timeout "The number of seconds to keep an empty R process alive before killing it.";
  at $ server location application;
  maxcount 1;
}

http_keepalive_timeout {
  desc "Defines how long a keepalive connection will sit between HTTP requests/responses before it is closed. Defaults to 45 seconds.";
  param Float timeout "The number of seconds to keep a connection alive between requests/responses.";
  at $;
  maxcount 1;
}

http_allow_compression {
  desc "Whether gzip/deflate compression is supported for HTTP responses. If this directive is not included, the default behavior is to support gzip/deflate compression.";
  param Boolean [enabled] "Whether or not this is enabled. Default is true." true;
  at $;
  maxcount 1;
}

sockjs_heartbeat_delay {
  desc "How often the SockJS server should send heartbeat packets to the server. These are used to prevent proxies and load balancers from closing active SockJS connections. Defaults to 25 seconds.";
  param Float delay "The number of seconds to wait between heartbeat packets.";
  at $;
  maxcount 1;
}

sockjs_disconnect_delay {
  desc "How long the SockJS server should wait between HTTP requests before considering the client to be disconnected. Defaults to 5 seconds. If this value needs to be adjusted above 10 seconds, it's a good idea to disable websockets using the `disable_websockets` directive, as that transport protocol has an effective 10 second limit built in.";
  param Float delay "The number of seconds to wait before giving up.";
  at $;
  maxcount 1;
}

simple_scheduler {
  desc "A basic scheduler which will spawn one single-threaded R worker for each application. If no scheduler is specified, this is the default scheduler.";
  param Integer [maxRequests] "The maximum number of requests to assign to this scheduler before it should start returning rejecting incoming traffic using a '503 - Service Unavailable' message. Once this threshold is hit, users attempting to initialize a new session will receive 503 errors." 100;
  at $ server location application;
  maxcount 1;
}

allow_app_override {
  desc "If present, will allow users to override the global defaults for a scheduler by customizing the parameters associated with a scheduler or even the type of scheduler used.";
  at $;
  param Boolean [enabled] "Whether or not this is enabled. Default is true." true;
  maxcount 1;
}

application {
  desc "DEPRECATED. This setting is deprecated and no longer enforced in Shiny Server. It will be ignored.";
  param String empty "";
  at location;
}

template_dir {
  desc "A directory containing custom templates to be used when generating pages in Shiny Server.";
  param String dir "The directory containing HTML templates.";
  at $ server location;
  maxcount 1;
}

python {
  desc "Specifies the Python executable (or virtual environment) that should be used to execute Shiny for Python applications.";
  param String path "One of the following: 1) the absolute path to a Python executable, 2) the absolute path to a virtualenv/venv directory, 3) a bare executable name (e.g. `python3.9`) which can be found on the PATH, 4) a relative path (to a Python executable or virtualenv/venv directory) to be resolved starting from the directory containing the Shiny for Python application.";
  at $ server location;
  maxcount 1;
}

bookmark_state_dir {
  desc "A directory for storing persisted application state. If Shiny Server is running without root privileges, then the `run_as` account must have read/write access to this directory. If no `bookmark_state_dir` directive is provided, `/var/lib/shiny-server/bookmarks` will be used.";
  param String dir "The directory where bookmark data should be stored.";
  at $ server location;
  maxcount 1;
}

disable_websockets {
  desc "Disable WebSockets on connections to the server. Some networks will not reliably support WebSockets, so this setting can be used to force Shiny Server to fall back to another protocol to communicate with the server. This is equivalent to adding 'websocket' to `disable_protocols`";
  param Boolean [val] "Whether or not WebSockets should be disabled." true;
  at $ server location;
  maxcount 1;
}

disable_protocols {
  desc "Disable some of the SockJS protocols used to establish a connection between your users and your server. Some network configurations cause problems with particular protocols; this option allows you to disable those. If your Shiny apps are loading but are unable to show outputs or maintain connections, try disabling 'websocket', then both 'websocket' and 'streaming'. If problems persist, it's unlikely that they are caused by compatibilities with SockJS, as the only remaining protocols are 'polling' which should work well with just about any reasonable HTTP proxy, load balancer, VPN, etc.";
  param String names... "The protocol(s) to disable. Available protocols are: 'websocket', 'xdr-streaming', 'xhr-streaming', 'eventsource', 'iframe-eventsource', 'htmlfile', 'iframe-htmlfile', 'xdr-polling', 'xhr-polling', 'iframe-xhr-polling', 'jsonp-polling'. You can also specify 'streaming' to disable all protocols that use streaming, and 'polling' to disable all protocols that use polling. Note: The eventsource and htmlfile protocols were introduced in v1.5.17. To prevent breaking existing Shiny Server installations with carefully configured protocol lists, the eventsource or htmlfile protocols will be disabled if iframe-eventsource or iframe-htmlfile protocols (respectively) are disabled.";
  at $ server location;
  maxcount 1;
}

preserve_logs {
  desc "By default, log files from Shiny processes that exited successfully (exit status 0) will be deleted. This behavior can be overridden by setting this property to `true` in which case Shiny Server will not delete the log files from any Shiny process that it spawns. WARNING: This feature should only be enabled when combined with proper log rotation. Otherwise, thousands of log files could quickly accrue and cause problems for the file system on which they are stored.";
  param Boolean [enabled] "Whether or not logs should be preserved." false;
  at $;
  maxcount 1;
}

log_as_user {
  desc "By default, the log files for R processes are created and managed by the user running the server centrally (often root). In the typical scenario in which the logs are stored in a server-wide directory, this is desirable as only root user may have write access to such a directory. In other cases, such as using `user_dirs` on a system in which the users' home directories are on an NFS mount which uses `root_squash`, creating log files as root may be a problem. In those scenarios, this option can be set to true to have the log files created by the users running the associated processes.";
  param Boolean [enabled] "Whether or not the log files should be managed by the owner of the process to which they belong." false;
  at $ server location;
  maxcount 1;
}

reconnect {
  desc "When a user's connection to the server is interrupted, Shiny Server will offer them a dialog that allows them to reconnect to their existing Shiny session for 15 seconds. This implies that the server will keep the Shiny session active on the server for an extra 15 seconds after a user disconnects in case they reconnect. After the 15 seconds, the user's session will be reaped and they will be notified and offered an opportunity to refresh the page. If this setting is true, the server will immediately reap the session of any user who is disconnected.";
  param Boolean [enabled] "Whether or not to offer to automatically reconnect disconnected users." true;
  at $ server location;
  maxcount 1;
}

sanitize_errors {
  desc "If this setting is true (the default), only generic error messages will be shown to the client (unless these were wrapped in `safeError()`).";
  param Boolean [enabled] "Whether or not to sanitize error messages on the client." true;
  at $ server location;
  maxcount 1;
}

frame_options {
  desc "Sets the X-Frame-Options header on URLs served from Shiny applications, to prevent the app from being embedded in a browser frame or iframe. This can be used as a mitigation for clickjacking attacks. If no option is provided, the default behavior is `allow`.";
  param String value "One of `allow`, `deny`, `sameorigin`, or `allow-from` (case insensitive). (`allow` removes the X-Frame-Options header.)";
  param String [url] "If `value` is `allow-from`, the URL from which framing should be allowed.";
  at $ server location;
  maxcount 1;
}
